Repository: zeromicro/go-zero
Pull request #1052 (2021-09-16 08:25:42)

update goctl api
`goctl api new` command support `--home` flag

```
NAME:
   goctl api new - fast create api service

USAGE:
   goctl api new [command options] [arguments...]

OPTIONS:
   --home value  the goctl home path of the template
```


Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 00000000..012b098b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,40 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior, if applicable:
+
+1. The code is
+
+   ```go
+   
+   ```
+
+2. The error is
+
+   ```
+   
+   ```
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Environments (please complete the following information):**
+ - OS: [e.g. Linux]
+ - go-zero version [e.g. 1.2.1]
+ - goctl version [e.g. 1.2.1, optional]
+
+**More description**
+Add any other context about the problem here.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 00000000..bbcbbe7d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
new file mode 100644
index 00000000..5e3f141b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.md
@@ -0,0 +1,10 @@
+---
+name: Question
+about: Ask a question on using go-zero or goctl
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+
diff --git a/core/errorx/atomicerror.go b/core/errorx/atomicerror.go
index bc52d54c..2a3db80e 100644
--- a/core/errorx/atomicerror.go
+++ b/core/errorx/atomicerror.go
@@ -9,7 +9,9 @@ type AtomicError struct {
 
 // Set sets the error.
 func (ae *AtomicError) Set(err error) {
-	ae.err.Store(err)
+	if err != nil {
+		ae.err.Store(err)
+	}
 }
 
 // Load returns the error.
diff --git a/core/service/serviceconf.go b/core/service/serviceconf.go
index 46bea43d..6a36e682 100644
--- a/core/service/serviceconf.go
+++ b/core/service/serviceconf.go
@@ -29,7 +29,7 @@ type ServiceConf struct {
 	Mode       string            `json:",default=pro,options=dev|test|rt|pre|pro"`
 	MetricsUrl string            `json:",optional"`
 	Prometheus prometheus.Config `json:",optional"`
-	// TODO: enable it in v1.2.1
+	// TODO: enable it in v1.2.2
 	// Telemetry opentelemetry.Config `json:",optional"`
 }
 
@@ -52,7 +52,7 @@ func (sc ServiceConf) SetUp() error {
 	sc.initMode()
 	prometheus.StartAgent(sc.Prometheus)
 
-	// TODO: enable it in v1.2.1
+	// TODO: enable it in v1.2.2
 	// if len(sc.Telemetry.Name) == 0 {
 	// 	sc.Telemetry.Name = sc.Name
 	// }
diff --git a/core/trace/opentelemetry/agent.go b/core/trace/opentelemetry/agent.go
index fdb70b77..d9825fe2 100644
--- a/core/trace/opentelemetry/agent.go
+++ b/core/trace/opentelemetry/agent.go
@@ -51,18 +51,12 @@ func StartAgent(c Config) {
 		)
 
 		otel.SetTracerProvider(tp)
-		otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
-		otel.SetErrorHandler(otelErrHandler{})
+		otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
+			propagation.TraceContext{}, propagation.Baggage{}))
+		otel.SetErrorHandler(otel.ErrorHandlerFunc(func(e error) {
+			logx.Errorf("[otel] error: %v", err)
+		}))
 
 		enabled.Set(true)
 	})
 }
-
-// errHandler handing otel errors.
-type otelErrHandler struct{}
-
-var _ otel.ErrorHandler = otelErrHandler{}
-
-func (o otelErrHandler) Handle(err error) {
-	logx.Errorf("[otel] error: %v", err)
-}
diff --git a/go.mod b/go.mod
index 34ea7d6b..d7160de1 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,6 @@ require (
 	github.com/DATA-DOG/go-sqlmock v1.4.1
 	github.com/alicebob/miniredis/v2 v2.14.1
 	github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
-	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 	github.com/emicklei/proto v1.9.0
 	github.com/fatih/color v1.9.0 // indirect
 	github.com/fatih/structtag v1.2.0
@@ -16,8 +15,8 @@ require (
 	github.com/go-redis/redis v6.15.7+incompatible
 	github.com/go-sql-driver/mysql v1.5.0
 	github.com/go-xorm/builder v0.3.4
+	github.com/golang-jwt/jwt v3.2.1+incompatible
 	github.com/golang/mock v1.4.3
-	github.com/golang/protobuf v1.5.2
 	github.com/google/uuid v1.1.2
 	github.com/iancoleman/strcase v0.1.2
 	github.com/justinas/alice v1.2.0
@@ -33,18 +32,20 @@ require (
 	github.com/urfave/cli v1.22.5
 	github.com/zeromicro/antlr v0.0.1
 	github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348
+	github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35
 	go.etcd.io/etcd/api/v3 v3.5.0
 	go.etcd.io/etcd/client/v3 v3.5.0
-	go.opentelemetry.io/otel v1.0.0-RC2
-	go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2
-	go.opentelemetry.io/otel/sdk v1.0.0-RC2
-	go.opentelemetry.io/otel/trace v1.0.0-RC2
+	go.opentelemetry.io/otel v1.0.0
+	go.opentelemetry.io/otel/exporters/jaeger v1.0.0
+	go.opentelemetry.io/otel/sdk v1.0.0
+	go.opentelemetry.io/otel/trace v1.0.0
 	go.uber.org/automaxprocs v1.3.0
-	golang.org/x/net v0.0.0-20210716203947-853a461950ff
-	golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect
+	golang.org/x/net v0.0.0-20210917221730-978cfadd31cf // indirect
+	golang.org/x/sys v0.0.0-20210921065528-437939a70204 // indirect
+	golang.org/x/text v0.3.7 // indirect
 	golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
-	google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
-	google.golang.org/grpc v1.39.0
+	google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect
+	google.golang.org/grpc v1.40.0
 	google.golang.org/protobuf v1.27.1
 	gopkg.in/cheggaaa/pb.v1 v1.0.28
 	gopkg.in/h2non/gock.v1 v1.0.15
diff --git a/go.sum b/go.sum
index 1b93732f..04036441 100644
--- a/go.sum
+++ b/go.sum
@@ -37,6 +37,7 @@ github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHg
 github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
 github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -59,6 +60,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
 github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
 github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
+github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
 github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -80,7 +83,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
 github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
@@ -144,6 +146,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
+github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -318,6 +322,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
 github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
 github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
@@ -346,6 +351,8 @@ github.com/zeromicro/antlr v0.0.1 h1:CQpIn/dc0pUjgGQ81y98s/NGOm2Hfru2NNio2I9mQgk
 github.com/zeromicro/antlr v0.0.1/go.mod h1:nfpjEwFR6Q4xGDJMcZnCL9tEfQRgszMwu3rDz2Z+p5M=
 github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348 h1:OhxL9tn28gDeJVzreIUiE5oVxZCjL3tBJ0XBNw8p5R8=
 github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiHrb9f5XGiYbo8=
+github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35 h1:LKLiozf78evAX4+82AHw/rG7TvefD7TJII7XB7Oip7o=
+github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35/go.mod h1:CJvyESptK/6uU5003fPJQ9Hmubl3vRuGqaLgzUU0R7Y=
 go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
@@ -356,14 +363,14 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
 go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg=
-go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM=
-go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2 h1:RF0nWsIDpDBe+s06lkLxUw9CWQUAhO6hBSxxB7dz45s=
-go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2/go.mod h1:sZZqN3Vb0iT+NE6mZ1S7sNyH3t4PFk6ElK5TLGFBZ7E=
-go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs=
-go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw=
-go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w=
-go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4=
+go.opentelemetry.io/otel v1.0.0 h1:qTTn6x71GVBvoafHK/yaRUmFzI4LcONZD0/kXxl5PHI=
+go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
+go.opentelemetry.io/otel/exporters/jaeger v1.0.0 h1:cLhx8llHw02h5JTqGqaRbYn+QVKHmrzD9vEbKnSPk5U=
+go.opentelemetry.io/otel/exporters/jaeger v1.0.0/go.mod h1:q10N1AolE1JjqKrFJK2tYw0iZpmX+HBaXBtuCzRnBGQ=
+go.opentelemetry.io/otel/sdk v1.0.0 h1:BNPMYUONPNbLneMttKSjQhOTlFLOD9U22HNG1KrIN2Y=
+go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
+go.opentelemetry.io/otel/trace v1.0.0 h1:TSBr8GTEtKevYMG/2d21M989r5WJYVimhTHBKVEZuh4=
+go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -441,8 +448,8 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds=
-golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
+golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -500,8 +507,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4=
-golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210921065528-437939a70204 h1:JJhkWtBuTQKyz2bd5WG9H8iUsJRU3En/KRfN8B2RnDs=
+golang.org/x/sys v0.0.0-20210921065528-437939a70204/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -510,8 +517,9 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -595,8 +603,8 @@ google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfG
 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
 google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f h1:YORWxaStkWBnWgELOHTmDrqNlFXuVGEbhwbB5iK94bQ=
-google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
+google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 h1:ysnBoUyeL/H6RCvNRhWHjKoDEmguI+mPU+qHgK8qv/w=
+google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -608,8 +616,8 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
 google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
 google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
 google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
-google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
+google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
 google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
diff --git a/readme-cn.md b/readme-cn.md
index 761b04fb..8a59342d 100644
--- a/readme-cn.md
+++ b/readme-cn.md
@@ -11,9 +11,11 @@
 [![Release](https://img.shields.io/github/v/release/tal-tech/go-zero.svg?style=flat-square)](https://github.com/tal-tech/go-zero)
 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
 
+**注意：为了满足开源基金会要求，go-zero 从好未来（tal-tech）组织下迁移至中立的 GitHub 组织（zeromicro）。**
+
 ## 0. go-zero 介绍
 
-go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性，经受了充分的实战检验。
+go-zero（收录于 CNCF 云原生技术全景图：[https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)）是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性，经受了充分的实战检验。
 
 go-zero 包含极简的 API 定义和生成工具 goctl，可以根据定义的 api 文件一键生成 Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript 代码，并可直接运行。
 
@@ -223,6 +225,7 @@ go-zero 已被许多公司用于生产部署，接入场景如在线教育、电
 >39. 深圳无边界技术有限公司
 >40. 马鞍山百助网络科技有限公司
 >41. 上海阿莫尔科技有限公司
+>42. 发明者量化
 
 如果贵公司也已使用 go-zero，欢迎在 [登记地址](https://github.com/tal-tech/go-zero/issues/602) 登记，仅仅为了推广，不做其它用途。
 
diff --git a/readme.md b/readme.md
index fe76eee3..5449bf4b 100644
--- a/readme.md
+++ b/readme.md
@@ -10,9 +10,11 @@ English | [简体中文](readme-cn.md)
 [![Release](https://img.shields.io/github/v/release/tal-tech/go-zero.svg?style=flat-square)](https://github.com/tal-tech/go-zero)
 [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
 
+**Note: To meet the requirements of Open Source Foundation, we moved go-zero from tal-tech to zeromicro (a neutral GitHub organization).**
+
 ## 0. what is go-zero
 
-go-zero is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design, and has been serving sites with tens of millions users for years.
+go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. It’s born to ensure the stability of the busy services with resilience design, and has been serving sites with tens of millions users for years.
 
 go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`.
 
diff --git a/rest/handler/authhandler.go b/rest/handler/authhandler.go
index 14dd7e7f..cf740e5e 100644
--- a/rest/handler/authhandler.go
+++ b/rest/handler/authhandler.go
@@ -8,7 +8,7 @@ import (
 	"net/http"
 	"net/http/httputil"
 
-	"github.com/dgrijalva/jwt-go"
+	"github.com/golang-jwt/jwt"
 	"github.com/tal-tech/go-zero/core/logx"
 	"github.com/tal-tech/go-zero/rest/token"
 )
diff --git a/rest/token/tokenparser.go b/rest/token/tokenparser.go
index 4326ae80..0500bb0f 100644
--- a/rest/token/tokenparser.go
+++ b/rest/token/tokenparser.go
@@ -6,8 +6,8 @@ import (
 	"sync/atomic"
 	"time"
 
-	"github.com/dgrijalva/jwt-go"
-	"github.com/dgrijalva/jwt-go/request"
+	"github.com/golang-jwt/jwt"
+	"github.com/golang-jwt/jwt/request"
 	"github.com/tal-tech/go-zero/core/timex"
 )
 
diff --git a/tools/goctl/api/gogen/util.go b/tools/goctl/api/gogen/util.go
index 106688b1..aa9ba8fc 100644
--- a/tools/goctl/api/gogen/util.go
+++ b/tools/goctl/api/gogen/util.go
@@ -70,7 +70,20 @@ func getParentPackage(dir string) (string, error) {
 		return "", err
 	}
 
-	return filepath.ToSlash(filepath.Join(projectCtx.Path, strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir))), nil
+	// fix https://github.com/zeromicro/go-zero/issues/1058
+	wd := projectCtx.WorkDir
+	d := projectCtx.Dir
+	same, err := ctlutil.SameFile(wd, d)
+	if err != nil {
+		return "", err
+	}
+
+	trim := strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir)
+	if same {
+		trim = strings.TrimPrefix(strings.ToLower(projectCtx.WorkDir), strings.ToLower(projectCtx.Dir))
+	}
+
+	return filepath.ToSlash(filepath.Join(projectCtx.Path, trim)), nil
 }
 
 func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int) error {
diff --git a/tools/goctl/api/new/newservice.go b/tools/goctl/api/new/newservice.go
index 86e87ae3..e76b96e7 100644
--- a/tools/goctl/api/new/newservice.go
+++ b/tools/goctl/api/new/newservice.go
@@ -59,7 +59,18 @@ func CreateServiceCommand(c *cli.Context) error {
 	}
 
 	defer fp.Close()
-	t := template.Must(template.New("template").Parse(apiTemplate))
+
+	home := c.String("home")
+	if len(home) > 0 {
+		util.RegisterGoctlHome(home)
+	}
+
+	text, err := util.LoadTemplate(category, apiTemplateFile, apiTemplate)
+	if err != nil {
+		return err
+	}
+
+	t := template.Must(template.New("template").Parse(text))
 	if err := t.Execute(fp, map[string]string{
 		"name":    dirName,
 		"handler": strings.Title(dirName),
diff --git a/tools/goctl/api/new/template.go b/tools/goctl/api/new/template.go
new file mode 100644
index 00000000..c467c6f1
--- /dev/null
+++ b/tools/goctl/api/new/template.go
@@ -0,0 +1,51 @@
+package new
+
+import (
+	"fmt"
+
+	"github.com/tal-tech/go-zero/tools/goctl/util"
+	"github.com/urfave/cli"
+)
+
+const (
+	category        = "newapi"
+	apiTemplateFile = "newtemplate.tpl"
+)
+
+var templates = map[string]string{
+	apiTemplateFile: apiTemplate,
+}
+
+// Category returns the category of the api files.
+func Category() string {
+	return category
+}
+
+// Clean cleans the generated deployment files.
+func Clean() error {
+	return util.Clean(category)
+}
+
+// GenTemplates generates api template files.
+func GenTemplates(_ *cli.Context) error {
+	return util.InitTemplates(category, templates)
+}
+
+// RevertTemplate reverts the given template file to the default value.
+func RevertTemplate(name string) error {
+	content, ok := templates[name]
+	if !ok {
+		return fmt.Errorf("%s: no such file name", name)
+	}
+	return util.CreateTemplate(category, name, content)
+}
+
+// Update updates the template files to the templates built in current goctl.
+func Update() error {
+	err := Clean()
+	if err != nil {
+		return err
+	}
+
+	return util.InitTemplates(category, templates)
+}
diff --git a/tools/goctl/goctl.go b/tools/goctl/goctl.go
index 2568dc70..b6a1a041 100644
--- a/tools/goctl/goctl.go
+++ b/tools/goctl/goctl.go
@@ -3,7 +3,9 @@ package main
 import (
 	"fmt"
 	"os"
+	"path/filepath"
 	"runtime"
+	"syscall"
 
 	"github.com/logrusorgru/aurora"
 	"github.com/tal-tech/go-zero/core/load"
@@ -29,7 +31,10 @@ import (
 	rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/cli"
 	"github.com/tal-tech/go-zero/tools/goctl/tpl"
 	"github.com/tal-tech/go-zero/tools/goctl/upgrade"
+	"github.com/tal-tech/go-zero/tools/goctl/util/console"
+	"github.com/tal-tech/go-zero/tools/goctl/util/env"
 	"github.com/urfave/cli"
+	pluginCtl "github.com/zeromicro/protobuf/protoc-gen-go"
 )
 
 var commands = []cli.Command{
@@ -57,6 +62,12 @@ var commands = []cli.Command{
 				Name:   "new",
 				Usage:  "fast create api service",
 				Action: new.CreateServiceCommand,
+				Flags: []cli.Flag{
+					cli.StringFlag{
+						Name:  "home",
+						Usage: "the goctl home path of the template",
+					},
+				},
 			},
 			{
 				Name:  "format",
@@ -637,6 +648,13 @@ func main() {
 	load.Disable()
 	stat.DisableLog()
 
+	args := os.Args
+	pluginName := filepath.Base(args[0])
+	if pluginName == protocGenGoctl {
+		pluginCtl.Generate()
+		return
+	}
+
 	app := cli.NewApp()
 	app.Usage = "a cli tool to generate code"
 	app.Version = fmt.Sprintf("%s %s/%s", version.BuildVersion, runtime.GOOS, runtime.GOARCH)
@@ -646,3 +664,33 @@ func main() {
 		fmt.Println(aurora.Red(errorx.Wrap(err).Error()))
 	}
 }
+
+func init() {
+	err := linkProtocGenGoctl()
+	if err != nil {
+		console.Error("%+v", err)
+	}
+}
+
+const protocGenGoctl = "protoc-gen-goctl"
+
+func linkProtocGenGoctl() error {
+	path, err := env.LookPath("goctl")
+	if err != nil {
+		return err
+	}
+
+	dir := filepath.Dir(path)
+	ext := filepath.Ext(path)
+	target := filepath.Join(dir, protocGenGoctl)
+	if len(ext) > 0 {
+		target = target + ext
+	}
+
+	err = syscall.Unlink(target)
+	if err != nil && !os.IsNotExist(err) {
+		return err
+	}
+
+	return os.Symlink(path, target)
+}
diff --git a/tools/goctl/internal/version/version.go b/tools/goctl/internal/version/version.go
index d89c4a4b..5d60e9d7 100644
--- a/tools/goctl/internal/version/version.go
+++ b/tools/goctl/internal/version/version.go
@@ -6,7 +6,7 @@ import (
 )
 
 // BuildVersion is the version of goctl.
-const BuildVersion = "1.2.1"
+const BuildVersion = "1.2.2-beta"
 
 // GetGoctlVersion returns BuildVersion
 func GetGoctlVersion() string {
@@ -48,7 +48,7 @@ func convertVersion(version string) (versionNumber float64, tag string) {
 		}
 		return '_'
 	}, splits[0])
-	numberStr = strings.ReplaceAll(numberStr, "_", "")
+	numberStr = strings.Replace(numberStr, "_", "", -1)
 	versionNumber, _ = json.Number(numberStr).Float64()
 	return
 }
diff --git a/tools/goctl/rpc/README.md b/tools/goctl/rpc/README.md
index f277a2c9..231c5359 100644
--- a/tools/goctl/rpc/README.md
+++ b/tools/goctl/rpc/README.md
@@ -163,12 +163,6 @@ OPTIONS:
 
 ### 注意事项
 
-* `google.golang.org/grpc`需要降级到 `v1.29.1`，且protoc-gen-go版本不能高于v1.3.2（see [https://github.com/grpc/grpc-go/issues/3347](https://github.com/grpc/grpc-go/issues/3347)）即
-  
-  ```shell script
-  replace google.golang.org/grpc => google.golang.org/grpc v1.29.1
-  ```
-
 * proto不支持暂多文件同时生成
 * proto不支持外部依赖包引入，message不支持inline
 * 目前main文件、shared文件、handler文件会被强制覆盖，而和开发人员手动需要编写的则不会覆盖生成，这一类在代码头部均有
@@ -232,40 +226,9 @@ service Greet {
 ## 常见问题解决(go mod工程)
 
 * 错误一:
+```text
+A required privilege is not held by the client.
+```
+这个问题只有goctl 版本在`goctl.exe version 1.2.1` 以后的 Windows操作系统出现，主要原因是goctl需要以管理员身份运行，这样才能将`goctl.exe` 创建一个 `ptocot-gen-gcotl`
+的符号链接。
 
-  ```golang
-  pb/xx.pb.go:220:7: undefined: grpc.ClientConnInterface
-  pb/xx.pb.go:224:11: undefined: grpc.SupportPackageIsVersion6
-  pb/xx.pb.go:234:5: undefined: grpc.ClientConnInterface
-  pb/xx.pb.go:237:24: undefined: grpc.ClientConnInterface
-  ```
-
-  解决方法：请将`protoc-gen-go`版本降至v1.3.2及一下
-
-* 错误二:
-
-  ```golang
-
-  # go.etcd.io/etcd/clientv3/balancer/picker
-  ../../../go/pkg/mod/go.etcd.io/etcd@v0.0.0-20200402134248-51bdeb39e698/clientv3/balancer/picker/err.go:25:9: cannot use &errPicker literal (type *errPicker) as type Picker in return argument:*errPicker does not implement Picker (wrong type for Pick method)
-    have Pick(context.Context, balancer.PickInfo) (balancer.SubConn, func(balancer.DoneInfo), error)
-    want Pick(balancer.PickInfo) (balancer.PickResult, error)
-    ../../../go/pkg/mod/go.etcd.io/etcd@v0.0.0-20200402134248-51bdeb39e698/clientv3/balancer/picker/roundrobin_balanced.go:33:9: cannot use &rrBalanced literal (type *rrBalanced) as type Picker in return argument:
-    *rrBalanced does not implement Picker (wrong type for Pick method)
-		have Pick(context.Context, balancer.PickInfo) (balancer.SubConn, func(balancer.DoneInfo), error)
-    want Pick(balancer.PickInfo) (balancer.PickResult, error)
-    #github.com/tal-tech/go-zero/zrpc/internal/balancer/p2c
-    ../../../go/pkg/mod/github.com/tal-tech/go-zero@v1.0.12/zrpc/internal/balancer/p2c/p2c.go:41:32: not enough arguments in call to base.NewBalancerBuilder
-	have (string, *p2cPickerBuilder)
-  want (string, base.PickerBuilder, base.Config)
-  ../../../go/pkg/mod/github.com/tal-tech/go-zero@v1.0.12/zrpc/internal/balancer/p2c/p2c.go:58:9: cannot use &p2cPicker literal (type *p2cPicker) as type balancer.Picker in return argument:
-	*p2cPicker does not implement balancer.Picker (wrong type for Pick method)
-		have Pick(context.Context, balancer.PickInfo) (balancer.SubConn, func(balancer.DoneInfo), error)
-		want Pick(balancer.PickInfo) (balancer.PickResult, error)
-  ```
-
-  解决方法：
-  
-    ```golang
-    replace google.golang.org/grpc => google.golang.org/grpc v1.29.1
-    ```
diff --git a/tools/goctl/rpc/cli/cli.go b/tools/goctl/rpc/cli/cli.go
index 46ec562b..ad576b49 100644
--- a/tools/goctl/rpc/cli/cli.go
+++ b/tools/goctl/rpc/cli/cli.go
@@ -4,11 +4,9 @@ import (
 	"errors"
 	"fmt"
 	"path/filepath"
-	"runtime"
 
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/generator"
 	"github.com/tal-tech/go-zero/tools/goctl/util"
-	"github.com/tal-tech/go-zero/tools/goctl/util/env"
 	"github.com/urfave/cli"
 )
 
@@ -16,10 +14,6 @@ import (
 // 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 {
-	if err := prepare(); err != nil {
-		return err
-	}
-
 	src := c.String("src")
 	out := c.String("dir")
 	style := c.String("style")
@@ -47,22 +41,6 @@ func RPC(c *cli.Context) error {
 	return g.Generate(src, out, protoImportPath, goOptions...)
 }
 
-func prepare() error {
-	if !env.CanExec() {
-		return fmt.Errorf("%s: can not start new processes using os.StartProcess or exec.Command", runtime.GOOS)
-	}
-	if _, err := env.LookUpGo(); err != nil {
-		return err
-	}
-	if _, err := env.LookUpProtoc(); err != nil {
-		return err
-	}
-	if _, err := env.LookUpProtocGenGo(); err != nil {
-		return err
-	}
-	return nil
-}
-
 // 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 {
diff --git a/tools/goctl/rpc/generator/defaultgenerator.go b/tools/goctl/rpc/generator/defaultgenerator.go
index 61725161..68288d4d 100644
--- a/tools/goctl/rpc/generator/defaultgenerator.go
+++ b/tools/goctl/rpc/generator/defaultgenerator.go
@@ -1,9 +1,11 @@
 package generator
 
 import (
-	"os/exec"
+	"fmt"
+	"runtime"
 
 	"github.com/tal-tech/go-zero/tools/goctl/util/console"
+	"github.com/tal-tech/go-zero/tools/goctl/util/env"
 )
 
 // DefaultGenerator defines the environment needs of rpc service generation
@@ -25,17 +27,24 @@ func NewDefaultGenerator() Generator {
 // 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 {
+	if !env.CanExec() {
+		return fmt.Errorf("%s: can not start new processes using os.StartProcess or exec.Command", runtime.GOOS)
+	}
+
+	if _, err := env.LookUpGo(); err != nil {
 		return err
 	}
 
-	_, err = exec.LookPath("protoc")
-	if err != nil {
+	if _, err := env.LookUpProtoc(); err != nil {
 		return err
 	}
 
-	_, err = exec.LookPath("protoc-gen-go")
+	_, err := env.LookUpProtocGenGoctl()
+	if err == nil {
+		return nil
+	}
 
+	g.log.Warning("%+v", err)
+	_, err = env.LookUpProtocGenGo()
 	return err
 }
diff --git a/tools/goctl/rpc/generator/gencall.go b/tools/goctl/rpc/generator/gencall.go
index 58489fc2..cbfad52e 100644
--- a/tools/goctl/rpc/generator/gencall.go
+++ b/tools/goctl/rpc/generator/gencall.go
@@ -3,6 +3,7 @@ package generator
 import (
 	"fmt"
 	"path/filepath"
+	"sort"
 	"strings"
 
 	"github.com/emicklei/proto"
@@ -95,9 +96,11 @@ func (g *DefaultGenerator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf
 		alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName), fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
 	}
 
+	aliasKeys := alias.KeysStr()
+	sort.Strings(aliasKeys)
 	err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
 		"name":        callFilename,
-		"alias":       strings.Join(alias.KeysStr(), util.NL),
+		"alias":       strings.Join(aliasKeys, util.NL),
 		"head":        head,
 		"filePackage": dir.Base,
 		"package":     fmt.Sprintf(`"%s"`, ctx.GetPb().Package),
diff --git a/tools/goctl/rpc/generator/genpb.go b/tools/goctl/rpc/generator/genpb.go
index 683fe4c5..289b8067 100644
--- a/tools/goctl/rpc/generator/genpb.go
+++ b/tools/goctl/rpc/generator/genpb.go
@@ -10,6 +10,7 @@ import (
 	conf "github.com/tal-tech/go-zero/tools/goctl/config"
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/parser"
+	"github.com/tal-tech/go-zero/tools/goctl/util/env"
 )
 
 const googleProtocGenGoErr = `--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC`
@@ -17,6 +18,12 @@ const googleProtocGenGoErr = `--go_out: protoc-gen-go: plugins are not supported
 // 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, goOptions ...string) error {
+	var useGoctl bool
+	_, err := env.LookUpProtocGenGoctl()
+	if err == nil {
+		useGoctl = true
+	}
+
 	dir := ctx.GetPb()
 	cw := new(bytes.Buffer)
 	directory, base := filepath.Split(proto.Src)
@@ -50,10 +57,15 @@ func (g *DefaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto
 	}
 
 	cw.WriteString(" " + proto.Name)
+	outFlag := " --go_out"
+	if useGoctl {
+		outFlag = " --goctl_out"
+	}
+
 	if strings.Contains(proto.GoPackage, "/") {
-		cw.WriteString(" --go_out=plugins=grpc:" + ctx.GetMain().Filename)
+		cw.WriteString(outFlag + "=plugins=grpc:" + ctx.GetMain().Filename)
 	} else {
-		cw.WriteString(" --go_out=plugins=grpc:" + dir.Filename)
+		cw.WriteString(outFlag + "=plugins=grpc:" + dir.Filename)
 	}
 
 	// Compatible with version 1.4.0，github.com/golang/protobuf/protoc-gen-go@v1.4.0
@@ -66,7 +78,6 @@ func (g *DefaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto
 		}
 
 		optSet.AddStr(op)
-		cw.WriteString(" --go_opt=" + op)
 	}
 
 	var currentFileOpt string
@@ -82,13 +93,13 @@ func (g *DefaultGenerator) GenPb(ctx DirContext, protoImportPath []string, proto
 		currentFileOpt = " --go_opt=M" + base + "=."
 	}
 
-	if !optSet.Contains(currentFileOpt) {
+	if !optSet.Contains(currentFileOpt) && !useGoctl {
 		cw.WriteString(currentFileOpt)
 	}
 
 	command := cw.String()
 	g.log.Debug(command)
-	_, err := execx.Run(command, "")
+	_, err = execx.Run(command, "")
 	if err != nil {
 		if strings.Contains(err.Error(), googleProtocGenGoErr) {
 			return errors.New(`Unsupported plugin protoc-gen-go which installed from the following source:
diff --git a/tools/goctl/rpc/generator/prototmpl.go b/tools/goctl/rpc/generator/prototmpl.go
index f7149141..637cb03d 100644
--- a/tools/goctl/rpc/generator/prototmpl.go
+++ b/tools/goctl/rpc/generator/prototmpl.go
@@ -25,7 +25,7 @@ service {{.serviceName}} {
 }
 `
 
-// ProtoTmpl returns an sample of a proto file
+// ProtoTmpl returns a sample of a proto file
 func ProtoTmpl(out string) error {
 	protoFilename := filepath.Base(out)
 	serviceName := stringx.From(strings.TrimSuffix(protoFilename, filepath.Ext(protoFilename)))
diff --git a/tools/goctl/tpl/templates.go b/tools/goctl/tpl/templates.go
index ba250701..a3ecbe58 100644
--- a/tools/goctl/tpl/templates.go
+++ b/tools/goctl/tpl/templates.go
@@ -8,6 +8,7 @@ import (
 	"github.com/tal-tech/go-zero/core/errorx"
 	"github.com/tal-tech/go-zero/tools/goctl/api/apigen"
 	"github.com/tal-tech/go-zero/tools/goctl/api/gogen"
+	apinew "github.com/tal-tech/go-zero/tools/goctl/api/new"
 	"github.com/tal-tech/go-zero/tools/goctl/docker"
 	"github.com/tal-tech/go-zero/tools/goctl/kube"
 	mongogen "github.com/tal-tech/go-zero/tools/goctl/model/mongo/generate"
@@ -48,6 +49,9 @@ func GenTemplates(ctx *cli.Context) error {
 		func() error {
 			return apigen.GenTemplates(ctx)
 		},
+		func() error {
+			return apinew.GenTemplates(ctx)
+		},
 	); err != nil {
 		return err
 	}
@@ -97,6 +101,9 @@ func CleanTemplates(ctx *cli.Context) error {
 		func() error {
 			return apigen.Clean()
 		},
+		func() error {
+			return apinew.Clean()
+		},
 	)
 	if err != nil {
 		return err
@@ -135,6 +142,8 @@ func UpdateTemplates(ctx *cli.Context) (err error) {
 		return mongogen.Update()
 	case apigen.Category():
 		return apigen.Update()
+	case apinew.Category():
+		return apinew.Update()
 	default:
 		err = fmt.Errorf("unexpected category: %s", category)
 		return
@@ -170,6 +179,8 @@ func RevertTemplates(ctx *cli.Context) (err error) {
 		return mongogen.RevertTemplate(filename)
 	case apigen.Category():
 		return apigen.RevertTemplate(filename)
+	case apinew.Category():
+		return apinew.RevertTemplate(filename)
 	default:
 		err = fmt.Errorf("unexpected category: %s", category)
 		return
diff --git a/tools/goctl/util/console/console.go b/tools/goctl/util/console/console.go
index 36a48859..dacb8e02 100644
--- a/tools/goctl/util/console/console.go
+++ b/tools/goctl/util/console/console.go
@@ -23,7 +23,9 @@ type (
 		MarkDone()
 		Must(err error)
 	}
+
 	colorConsole struct{}
+
 	// for idea log
 	ideaConsole struct{}
 )
@@ -140,3 +142,37 @@ func println(msg interface{}) {
 
 	fmt.Println(msg)
 }
+
+var defaultConsole = new(colorConsole)
+
+func Success(format string, a ...interface{}) {
+	defaultConsole.Success(format, a...)
+}
+
+func Info(format string, a ...interface{}) {
+	defaultConsole.Info(format, a...)
+}
+
+func Debug(format string, a ...interface{}) {
+	defaultConsole.Debug(format, a...)
+}
+
+func Warning(format string, a ...interface{}) {
+	defaultConsole.Warning(format, a...)
+}
+
+func Error(format string, a ...interface{}) {
+	defaultConsole.Error(format, a...)
+}
+
+func Fatalln(format string, a ...interface{}) {
+	defaultConsole.Fatalln(format, a...)
+}
+
+func MarkDone() {
+	defaultConsole.MarkDone()
+}
+
+func Must(err error) {
+	defaultConsole.Must(err)
+}
diff --git a/tools/goctl/util/env/env.go b/tools/goctl/util/env/env.go
index 9e9e0a77..6bcef662 100644
--- a/tools/goctl/util/env/env.go
+++ b/tools/goctl/util/env/env.go
@@ -11,10 +11,11 @@ import (
 )
 
 const (
-	bin            = "bin"
-	binGo          = "go"
-	binProtoc      = "protoc"
-	binProtocGenGo = "protoc-gen-go"
+	bin               = "bin"
+	binGo             = "go"
+	binProtoc         = "protoc"
+	binProtocGenGo    = "protoc-gen-go"
+	binProtocGenGoctl = "protoc-gen-goctl"
 )
 
 // LookUpGo searches an executable go in the directories
@@ -38,14 +39,22 @@ func LookUpProtoc() (string, error) {
 	return LookPath(xProtoc)
 }
 
-// LookUpProtocGenGo searches an executable protoc-gen-go in the directories
-// named by the PATH environment variable.
+// Deprecated: LookUpProtocGenGo searches an executable protoc-gen-go in the directories
+// named by the PATH environment variable, use LookUpProtocGenGoctl instead.
 func LookUpProtocGenGo() (string, error) {
 	suffix := getExeSuffix()
 	xProtocGenGo := binProtocGenGo + suffix
 	return LookPath(xProtocGenGo)
 }
 
+// LookUpProtocGenGoctl searches an executable protoc-gen-go in the directories
+// named by the PATH environment variable.
+func LookUpProtocGenGoctl() (string, error) {
+	suffix := getExeSuffix()
+	xProtocGenGo := binProtocGenGoctl + suffix
+	return LookPath(xProtocGenGo)
+}
+
 // LookPath searches for an executable named file in the
 // directories named by the PATH environment variable,
 // for the os windows, the named file will be spliced with the
diff --git a/tools/goctl/util/file.go b/tools/goctl/util/file.go
index b8ef6bf2..5b42a51d 100644
--- a/tools/goctl/util/file.go
+++ b/tools/goctl/util/file.go
@@ -4,6 +4,7 @@ import (
 	"bufio"
 	"fmt"
 	"io/ioutil"
+	"log"
 	"os"
 	"path/filepath"
 	"strings"
@@ -148,6 +149,24 @@ func LoadTemplate(category, file, builtin string) (string, error) {
 	return string(content), nil
 }
 
+// SameFile compares the between path if the same path,
+// it maybe the same path in case case-ignore, such as:
+// /Users/go_zero and /Users/Go_zero, as far as we know,
+// this case maybe appear on macOS and Windows.
+func SameFile(path1, path2 string) (bool, error) {
+	stat1, err := os.Stat(path1)
+	if err != nil {
+		return false, err
+	}
+
+	stat2, err := os.Stat(path2)
+	if err != nil {
+		return false, err
+	}
+
+	return os.SameFile(stat1, stat2), nil
+}
+
 func createTemplate(file, content string, force bool) error {
 	if FileExists(file) && !force {
 		return nil
@@ -162,3 +181,13 @@ func createTemplate(file, content string, force bool) error {
 	_, err = f.WriteString(content)
 	return err
 }
+
+// MustTempDir creates a temporary directory
+func MustTempDir() string {
+	dir, err := ioutil.TempDir("", "")
+	if err != nil {
+		log.Fatalln(err)
+	}
+
+	return dir
+}
diff --git a/tools/goctl/util/stringx/string.go b/tools/goctl/util/stringx/string.go
index 1e3e6161..ae148c2f 100644
--- a/tools/goctl/util/stringx/string.go
+++ b/tools/goctl/util/stringx/string.go
@@ -39,7 +39,7 @@ func (s String) Upper() string {
 
 // ReplaceAll calls the strings.ReplaceAll
 func (s String) ReplaceAll(old, new string) string {
-	return strings.ReplaceAll(s.source, old, new)
+	return strings.Replace(s.source, old, new, -1)
 }
 
 // Source returns the source string value
diff --git a/zrpc/internal/mock/deposit.pb.go b/zrpc/internal/mock/deposit.pb.go
index 60a43c5a..32df60dd 100644
--- a/zrpc/internal/mock/deposit.pb.go
+++ b/zrpc/internal/mock/deposit.pb.go
@@ -1,119 +1,263 @@
-// Code generated by protoc-gen-go.
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.27.1
+// 	protoc        v3.8.0
 // source: deposit.proto
-// DO NOT EDIT!
 
-/*
-Package mock is a generated protocol buffer package.
-
-It is generated from these files:
-	deposit.proto
-
-It has these top-level messages:
-	DepositRequest
-	DepositResponse
-*/
 package mock
 
 import (
-	proto "github.com/golang/protobuf/proto"
-	fmt "fmt"
-	math "math"
-)
-
-import (
-	context "golang.org/x/net/context"
+	context "context"
 	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
 )
 
-// Reference imports to suppress errors if they are not otherwise used.
-var (
-	_ = proto.Marshal
-	_ = fmt.Errorf
-	_ = math.Inf
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 )
 
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
 type DepositRequest struct {
-	Amount float32 `protobuf:"fixed32,1,opt,name=amount" json:"amount,omitempty"`
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Amount float32 `protobuf:"fixed32,1,opt,name=amount,proto3" json:"amount,omitempty"`
 }
 
-func (m *DepositRequest) Reset()                    { *m = DepositRequest{} }
-func (m *DepositRequest) String() string            { return proto.CompactTextString(m) }
-func (*DepositRequest) ProtoMessage()               {}
-func (*DepositRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
+func (x *DepositRequest) Reset() {
+	*x = DepositRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_deposit_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DepositRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
 
-func (m *DepositRequest) GetAmount() float32 {
-	if m != nil {
-		return m.Amount
+func (*DepositRequest) ProtoMessage() {}
+
+func (x *DepositRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_deposit_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use DepositRequest.ProtoReflect.Descriptor instead.
+func (*DepositRequest) Descriptor() ([]byte, []int) {
+	return file_deposit_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *DepositRequest) GetAmount() float32 {
+	if x != nil {
+		return x.Amount
 	}
 	return 0
 }
 
 type DepositResponse struct {
-	Ok bool `protobuf:"varint,1,opt,name=ok" json:"ok,omitempty"`
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"`
+}
+
+func (x *DepositResponse) Reset() {
+	*x = DepositResponse{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_deposit_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *DepositResponse) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*DepositResponse) ProtoMessage() {}
+
+func (x *DepositResponse) ProtoReflect() protoreflect.Message {
+	mi := &file_deposit_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
 }
 
-func (m *DepositResponse) Reset()                    { *m = DepositResponse{} }
-func (m *DepositResponse) String() string            { return proto.CompactTextString(m) }
-func (*DepositResponse) ProtoMessage()               {}
-func (*DepositResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
+// Deprecated: Use DepositResponse.ProtoReflect.Descriptor instead.
+func (*DepositResponse) Descriptor() ([]byte, []int) {
+	return file_deposit_proto_rawDescGZIP(), []int{1}
+}
 
-func (m *DepositResponse) GetOk() bool {
-	if m != nil {
-		return m.Ok
+func (x *DepositResponse) GetOk() bool {
+	if x != nil {
+		return x.Ok
 	}
 	return false
 }
 
-func init() {
-	proto.RegisterType((*DepositRequest)(nil), "mock.DepositRequest")
-	proto.RegisterType((*DepositResponse)(nil), "mock.DepositResponse")
+var File_deposit_proto protoreflect.FileDescriptor
+
+var file_deposit_proto_rawDesc = []byte{
+	0x0a, 0x0d, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
+	0x04, 0x6d, 0x6f, 0x63, 0x6b, 0x22, 0x28, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
+	0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e,
+	0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22,
+	0x21, 0x0a, 0x0f, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
+	0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02,
+	0x6f, 0x6b, 0x32, 0x48, 0x0a, 0x0e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x53, 0x65, 0x72,
+	0x76, 0x69, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12,
+	0x14, 0x2e, 0x6d, 0x6f, 0x63, 0x6b, 0x2e, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65,
+	0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x6d, 0x6f, 0x63, 0x6b, 0x2e, 0x44, 0x65, 0x70,
+	0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x08, 0x5a, 0x06,
+	0x2e, 0x3b, 0x6d, 0x6f, 0x63, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
-// Reference imports to suppress errors if they are not otherwise used.
 var (
-	_ context.Context
-	_ grpc.ClientConn
+	file_deposit_proto_rawDescOnce sync.Once
+	file_deposit_proto_rawDescData = file_deposit_proto_rawDesc
 )
 
+func file_deposit_proto_rawDescGZIP() []byte {
+	file_deposit_proto_rawDescOnce.Do(func() {
+		file_deposit_proto_rawDescData = protoimpl.X.CompressGZIP(file_deposit_proto_rawDescData)
+	})
+	return file_deposit_proto_rawDescData
+}
+
+var file_deposit_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_deposit_proto_goTypes = []interface{}{
+	(*DepositRequest)(nil),  // 0: mock.DepositRequest
+	(*DepositResponse)(nil), // 1: mock.DepositResponse
+}
+var file_deposit_proto_depIdxs = []int32{
+	0, // 0: mock.DepositService.Deposit:input_type -> mock.DepositRequest
+	1, // 1: mock.DepositService.Deposit:output_type -> mock.DepositResponse
+	1, // [1:2] is the sub-list for method output_type
+	0, // [0:1] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_deposit_proto_init() }
+func file_deposit_proto_init() {
+	if File_deposit_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_deposit_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DepositRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_deposit_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*DepositResponse); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_deposit_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_deposit_proto_goTypes,
+		DependencyIndexes: file_deposit_proto_depIdxs,
+		MessageInfos:      file_deposit_proto_msgTypes,
+	}.Build()
+	File_deposit_proto = out.File
+	file_deposit_proto_rawDesc = nil
+	file_deposit_proto_goTypes = nil
+	file_deposit_proto_depIdxs = nil
+}
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ context.Context
+var _ grpc.ClientConnInterface
+
 // This is a compile-time assertion to ensure that this generated file
 // is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// Client API for DepositService service
+const _ = grpc.SupportPackageIsVersion6
 
+// DepositServiceClient is the client API for DepositService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
 type DepositServiceClient interface {
 	Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*DepositResponse, error)
 }
 
 type depositServiceClient struct {
-	cc *grpc.ClientConn
+	cc grpc.ClientConnInterface
 }
 
-func NewDepositServiceClient(cc *grpc.ClientConn) DepositServiceClient {
+func NewDepositServiceClient(cc grpc.ClientConnInterface) DepositServiceClient {
 	return &depositServiceClient{cc}
 }
 
 func (c *depositServiceClient) Deposit(ctx context.Context, in *DepositRequest, opts ...grpc.CallOption) (*DepositResponse, error) {
 	out := new(DepositResponse)
-	err := grpc.Invoke(ctx, "/mock.DepositService/Deposit", in, out, c.cc, opts...)
+	err := c.cc.Invoke(ctx, "/mock.DepositService/Deposit", in, out, opts...)
 	if err != nil {
 		return nil, err
 	}
 	return out, nil
 }
 
-// Server API for DepositService service
-
+// DepositServiceServer is the server API for DepositService service.
 type DepositServiceServer interface {
 	Deposit(context.Context, *DepositRequest) (*DepositResponse, error)
 }
 
+// UnimplementedDepositServiceServer can be embedded to have forward compatible implementations.
+type UnimplementedDepositServiceServer struct {
+}
+
+func (*UnimplementedDepositServiceServer) Deposit(context.Context, *DepositRequest) (*DepositResponse, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method Deposit not implemented")
+}
+
 func RegisterDepositServiceServer(s *grpc.Server, srv DepositServiceServer) {
 	s.RegisterService(&_DepositService_serviceDesc, srv)
 }
@@ -148,18 +292,3 @@ var _DepositService_serviceDesc = grpc.ServiceDesc{
 	Streams:  []grpc.StreamDesc{},
 	Metadata: "deposit.proto",
 }
-
-func init() { proto.RegisterFile("deposit.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
-	// 139 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4d, 0x49, 0x2d, 0xc8,
-	0x2f, 0xce, 0x2c, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0xc9, 0xcd, 0x4f, 0xce, 0x56,
-	0xd2, 0xe0, 0xe2, 0x73, 0x81, 0x08, 0x07, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x89, 0x71,
-	0xb1, 0x25, 0xe6, 0xe6, 0x97, 0xe6, 0x95, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x30, 0x05, 0x41, 0x79,
-	0x4a, 0x8a, 0x5c, 0xfc, 0x70, 0x95, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x7c, 0x5c, 0x4c,
-	0xf9, 0xd9, 0x60, 0x65, 0x1c, 0x41, 0x4c, 0xf9, 0xd9, 0x46, 0x1e, 0x70, 0xc3, 0x82, 0x53, 0x8b,
-	0xca, 0x32, 0x93, 0x53, 0x85, 0xcc, 0xb8, 0xd8, 0xa1, 0x22, 0x42, 0x22, 0x7a, 0x20, 0x0b, 0xf5,
-	0x50, 0x6d, 0x93, 0x12, 0x45, 0x13, 0x85, 0x98, 0x9c, 0xc4, 0x06, 0x76, 0xa3, 0x31, 0x20, 0x00,
-	0x00, 0xff, 0xff, 0x62, 0x37, 0xf2, 0x36, 0xb4, 0x00, 0x00, 0x00,
-}
diff --git a/zrpc/internal/mock/deposit.proto b/zrpc/internal/mock/deposit.proto
index b2896435..68ab1607 100644
--- a/zrpc/internal/mock/deposit.proto
+++ b/zrpc/internal/mock/deposit.proto
@@ -2,6 +2,8 @@ syntax = "proto3";
 
 package mock;
 
+option go_package = ".;mock";
+
 message DepositRequest {
   float amount = 1;
 }
@@ -12,4 +14,4 @@ message DepositResponse {
 
 service DepositService {
   rpc Deposit(DepositRequest) returns (DepositResponse);
-}
\ No newline at end of file
+}


Test patch:
diff --git a/core/errorx/atomicerror_test.go b/core/errorx/atomicerror_test.go
index d05f8866..10c7b44d 100644
--- a/core/errorx/atomicerror_test.go
+++ b/core/errorx/atomicerror_test.go
@@ -17,6 +17,15 @@ func TestAtomicError(t *testing.T) {
 	assert.Equal(t, errDummy, err.Load())
 }
 
+func TestAtomicErrorSetNil(t *testing.T) {
+	var (
+		errNil error
+		err    AtomicError
+	)
+	err.Set(errNil)
+	assert.Equal(t, errNil, err.Load())
+}
+
 func TestAtomicErrorNil(t *testing.T) {
 	var err AtomicError
 	assert.Nil(t, err.Load())
diff --git a/core/logx/rotatelogger_test.go b/core/logx/rotatelogger_test.go
index c7439545..15862bdc 100644
--- a/core/logx/rotatelogger_test.go
+++ b/core/logx/rotatelogger_test.go
@@ -100,7 +100,7 @@ func TestRotateLoggerRotate(t *testing.T) {
 	err = logger.rotate()
 	switch v := err.(type) {
 	case *os.LinkError:
-		// avoid rename error on ubuntu
+		// avoid rename error on docker container
 		assert.Equal(t, syscall.EXDEV, v.Err)
 	default:
 		assert.Nil(t, err)
diff --git a/rest/handler/authhandler_test.go b/rest/handler/authhandler_test.go
index 16e13d74..b0985e7e 100644
--- a/rest/handler/authhandler_test.go
+++ b/rest/handler/authhandler_test.go
@@ -8,7 +8,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/dgrijalva/jwt-go"
+	"github.com/golang-jwt/jwt"
 	"github.com/stretchr/testify/assert"
 )
 
diff --git a/rest/token/tokenparser_test.go b/rest/token/tokenparser_test.go
index 215b4db5..31929e91 100644
--- a/rest/token/tokenparser_test.go
+++ b/rest/token/tokenparser_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 	"time"
 
-	"github.com/dgrijalva/jwt-go"
+	"github.com/golang-jwt/jwt"
 	"github.com/stretchr/testify/assert"
 	"github.com/tal-tech/go-zero/core/timex"
 )
diff --git a/tools/goctl/api/parser/g4/test/apiparser_test.go b/tools/goctl/api/parser/g4/test/apiparser_test.go
index 03cd4cb1..13ebdffd 100644
--- a/tools/goctl/api/parser/g4/test/apiparser_test.go
+++ b/tools/goctl/api/parser/g4/test/apiparser_test.go
@@ -9,6 +9,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 var (
@@ -118,7 +119,7 @@ func TestApiParser(t *testing.T) {
 	})
 
 	t.Run("nestedImport", func(t *testing.T) {
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err := ioutil.WriteFile(file, []byte(nestedAPIImport), os.ModePerm)
 		if err != nil {
 			return
@@ -148,7 +149,7 @@ func TestApiParser(t *testing.T) {
 	})
 
 	t.Run("ambiguousSyntax", func(t *testing.T) {
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
 		if err != nil {
 			return
@@ -162,7 +163,7 @@ func TestApiParser(t *testing.T) {
 	})
 
 	t.Run("ambiguousSyntax", func(t *testing.T) {
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
 		if err != nil {
 			return
@@ -176,7 +177,7 @@ func TestApiParser(t *testing.T) {
 	})
 
 	t.Run("ambiguousService", func(t *testing.T) {
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err := ioutil.WriteFile(file, []byte(ambiguousService), os.ModePerm)
 		if err != nil {
 			return
@@ -206,7 +207,7 @@ func TestApiParser(t *testing.T) {
 		`)
 		assert.Error(t, err)
 
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err = ioutil.WriteFile(file, []byte(duplicateHandler), os.ModePerm)
 		if err != nil {
 			return
@@ -235,7 +236,7 @@ func TestApiParser(t *testing.T) {
 		`)
 		assert.Error(t, err)
 
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err = ioutil.WriteFile(file, []byte(duplicateRoute), os.ModePerm)
 		if err != nil {
 			return
@@ -259,7 +260,7 @@ func TestApiParser(t *testing.T) {
 		`)
 		assert.Error(t, err)
 
-		file := filepath.Join(t.TempDir(), "foo.api")
+		file := filepath.Join(util.MustTempDir(), "foo.api")
 		err = ioutil.WriteFile(file, []byte(duplicateType), os.ModePerm)
 		if err != nil {
 			return
diff --git a/tools/goctl/model/mongo/generate/generate_test.go b/tools/goctl/model/mongo/generate/generate_test.go
index 5298644b..c8032fcd 100644
--- a/tools/goctl/model/mongo/generate/generate_test.go
+++ b/tools/goctl/model/mongo/generate/generate_test.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/tal-tech/go-zero/tools/goctl/config"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 var testTypes = `
@@ -18,7 +19,7 @@ func TestDo(t *testing.T) {
 	cfg, err := config.NewConfig(config.DefaultFormat)
 	assert.Nil(t, err)
 
-	tempDir := t.TempDir()
+	tempDir := util.MustTempDir()
 	typesfile := filepath.Join(tempDir, "types.go")
 	err = ioutil.WriteFile(typesfile, []byte(testTypes), 0o666)
 	assert.Nil(t, err)
diff --git a/tools/goctl/model/sql/command/command_test.go b/tools/goctl/model/sql/command/command_test.go
index 72fe7020..ebdcf501 100644
--- a/tools/goctl/model/sql/command/command_test.go
+++ b/tools/goctl/model/sql/command/command_test.go
@@ -23,12 +23,12 @@ func TestFromDDl(t *testing.T) {
 	err := gen.Clean()
 	assert.Nil(t, err)
 
-	err = fromDDL("./user.sql", t.TempDir(), cfg, true, false, "go_zero")
+	err = fromDDL("./user.sql", util.MustTempDir(), cfg, true, false, "go_zero")
 	assert.Equal(t, errNotMatched, err)
 
 	// case dir is not exists
-	unknownDir := filepath.Join(t.TempDir(), "test", "user.sql")
-	err = fromDDL(unknownDir, t.TempDir(), cfg, true, false, "go_zero")
+	unknownDir := filepath.Join(util.MustTempDir(), "test", "user.sql")
+	err = fromDDL(unknownDir, util.MustTempDir(), cfg, true, false, "go_zero")
 	assert.True(t, func() bool {
 		switch err.(type) {
 		case *os.PathError:
@@ -39,12 +39,12 @@ func TestFromDDl(t *testing.T) {
 	}())
 
 	// case empty src
-	err = fromDDL("", t.TempDir(), cfg, true, false, "go_zero")
+	err = fromDDL("", util.MustTempDir(), cfg, true, false, "go_zero")
 	if err != nil {
 		assert.Equal(t, "expected path or path globbing patterns, but nothing found", err.Error())
 	}
 
-	tempDir := filepath.Join(t.TempDir(), "test")
+	tempDir := filepath.Join(util.MustTempDir(), "test")
 	err = util.MkdirIfNotExist(tempDir)
 	if err != nil {
 		return
diff --git a/tools/goctl/model/sql/gen/gen_test.go b/tools/goctl/model/sql/gen/gen_test.go
index 2d87e003..a2a59178 100644
--- a/tools/goctl/model/sql/gen/gen_test.go
+++ b/tools/goctl/model/sql/gen/gen_test.go
@@ -14,6 +14,7 @@ import (
 	"github.com/tal-tech/go-zero/core/stringx"
 	"github.com/tal-tech/go-zero/tools/goctl/config"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/builderx"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 var source = "CREATE TABLE `test_user` (\n  `id` bigint NOT NULL AUTO_INCREMENT,\n  `mobile` varchar(255) COLLATE utf8mb4_bin NOT NULL,\n  `class` bigint NOT NULL,\n  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `mobile_unique` (`mobile`),\n  UNIQUE KEY `class_name_unique` (`class`,`name`),\n  KEY `create_index` (`create_time`),\n  KEY `name_index` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;"
@@ -22,11 +23,11 @@ func TestCacheModel(t *testing.T) {
 	logx.Disable()
 	_ = Clean()
 
-	sqlFile := filepath.Join(t.TempDir(), "tmp.sql")
+	sqlFile := filepath.Join(util.MustTempDir(), "tmp.sql")
 	err := ioutil.WriteFile(sqlFile, []byte(source), 0o777)
 	assert.Nil(t, err)
 
-	dir := filepath.Join(t.TempDir(), "./testmodel")
+	dir := filepath.Join(util.MustTempDir(), "./testmodel")
 	cacheDir := filepath.Join(dir, "cache")
 	noCacheDir := filepath.Join(dir, "nocache")
 	g, err := NewDefaultGenerator(cacheDir, &config.Config{
@@ -57,7 +58,7 @@ func TestNamingModel(t *testing.T) {
 	logx.Disable()
 	_ = Clean()
 
-	sqlFile := filepath.Join(t.TempDir(), "tmp.sql")
+	sqlFile := filepath.Join(util.MustTempDir(), "tmp.sql")
 	err := ioutil.WriteFile(sqlFile, []byte(source), 0o777)
 	assert.Nil(t, err)
 
diff --git a/tools/goctl/model/sql/parser/parser_test.go b/tools/goctl/model/sql/parser/parser_test.go
index 25485fb9..8621d34a 100644
--- a/tools/goctl/model/sql/parser/parser_test.go
+++ b/tools/goctl/model/sql/parser/parser_test.go
@@ -8,10 +8,11 @@ import (
 	"github.com/stretchr/testify/assert"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
 	"github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
+	ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 func TestParsePlainText(t *testing.T) {
-	sqlFile := filepath.Join(t.TempDir(), "tmp.sql")
+	sqlFile := filepath.Join(ctlutil.MustTempDir(), "tmp.sql")
 	err := ioutil.WriteFile(sqlFile, []byte("plain text"), 0o777)
 	assert.Nil(t, err)
 
@@ -20,7 +21,7 @@ func TestParsePlainText(t *testing.T) {
 }
 
 func TestParseSelect(t *testing.T) {
-	sqlFile := filepath.Join(t.TempDir(), "tmp.sql")
+	sqlFile := filepath.Join(ctlutil.MustTempDir(), "tmp.sql")
 	err := ioutil.WriteFile(sqlFile, []byte("select * from user"), 0o777)
 	assert.Nil(t, err)
 
@@ -30,7 +31,7 @@ func TestParseSelect(t *testing.T) {
 }
 
 func TestParseCreateTable(t *testing.T) {
-	sqlFile := filepath.Join(t.TempDir(), "tmp.sql")
+	sqlFile := filepath.Join(ctlutil.MustTempDir(), "tmp.sql")
 	err := ioutil.WriteFile(sqlFile, []byte("CREATE TABLE `test_user` (\n  `id` bigint NOT NULL AUTO_INCREMENT,\n  `mobile` varchar(255) COLLATE utf8mb4_bin NOT NULL comment '手\\t机  号',\n  `class` bigint NOT NULL comment '班级',\n  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL comment '姓\n  名',\n  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP comment '创建\\r时间',\n  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `mobile_unique` (`mobile`),\n  UNIQUE KEY `class_name_unique` (`class`,`name`),\n  KEY `create_index` (`create_time`),\n  KEY `name_index` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;"), 0o777)
 	assert.Nil(t, err)
 
diff --git a/tools/goctl/rpc/generator/gen_test.go b/tools/goctl/rpc/generator/gen_test.go
index 31c28335..eb8cdefa 100644
--- a/tools/goctl/rpc/generator/gen_test.go
+++ b/tools/goctl/rpc/generator/gen_test.go
@@ -12,6 +12,7 @@ import (
 	"github.com/tal-tech/go-zero/core/stringx"
 	conf "github.com/tal-tech/go-zero/tools/goctl/config"
 	"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 var cfg = &conf.Config{
@@ -57,7 +58,7 @@ func TestRpcGenerate(t *testing.T) {
 
 	// case go mod
 	t.Run("GOMOD", func(t *testing.T) {
-		workDir := t.TempDir()
+		workDir := util.MustTempDir()
 		name := filepath.Base(workDir)
 		_, err = execx.Run("go mod init "+name, workDir)
 		if err != nil {
diff --git a/tools/goctl/rpc/generator/prototmpl_test.go b/tools/goctl/rpc/generator/prototmpl_test.go
index e735c9e5..6a13a3e5 100644
--- a/tools/goctl/rpc/generator/prototmpl_test.go
+++ b/tools/goctl/rpc/generator/prototmpl_test.go
@@ -5,16 +5,17 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/tal-tech/go-zero/tools/goctl/util"
 )
 
 func TestProtoTmpl(t *testing.T) {
 	_ = Clean()
 	// exists dir
-	err := ProtoTmpl(t.TempDir())
+	err := ProtoTmpl(util.MustTempDir())
 	assert.Nil(t, err)
 
 	// not exist dir
-	dir := filepath.Join(t.TempDir(), "test")
+	dir := filepath.Join(util.MustTempDir(), "test")
 	err = ProtoTmpl(dir)
 	assert.Nil(t, err)
 }