diff --git a/go.mod b/go.mod
index 090d3f93..c76614b0 100644
--- a/go.mod
+++ b/go.mod
@@ -54,6 +54,6 @@ require (
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect
golang.org/x/net v0.0.0-20220531201128-c960675eff93 // indirect
- google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8 // indirect
+ google.golang.org/genproto v0.0.0-20220602131408-e326c6e8e9c8
k8s.io/klog/v2 v2.40.1 // indirect
)
diff --git a/tools/goctl/example/rpc/hello.proto b/tools/goctl/example/rpc/hello.proto
new file mode 100644
index 00000000..0ea428d0
--- /dev/null
+++ b/tools/goctl/example/rpc/hello.proto
@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package hello;
+
+option go_package = "./hello";
+
+message HelloReq {
+ string in = 1;
+}
+
+message HelloResp {
+ string msg = 1;
+}
+
+service Greet {
+ rpc SayHello(HelloReq) returns (HelloResp);
+}
\ No newline at end of file
diff --git a/tools/goctl/example/rpc/hello/client/greet/greet.go b/tools/goctl/example/rpc/hello/client/greet/greet.go
new file mode 100644
index 00000000..ec9d3c18
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/client/greet/greet.go
@@ -0,0 +1,37 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hello.proto
+
+package client
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/pb/hello"
+
+ "github.com/zeromicro/go-zero/zrpc"
+ "google.golang.org/grpc"
+)
+
+type (
+ HelloReq = hello.HelloReq
+ HelloResp = hello.HelloResp
+
+ Greet interface {
+ SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error)
+ }
+
+ defaultGreet struct {
+ cli zrpc.Client
+ }
+)
+
+func NewGreet(cli zrpc.Client) Greet {
+ return &defaultGreet{
+ cli: cli,
+ }
+}
+
+func (m *defaultGreet) SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
+ client := hello.NewGreetClient(m.cli.Conn())
+ return client.SayHello(ctx, in, opts...)
+}
diff --git a/tools/goctl/example/rpc/hello/etc/hello.yaml b/tools/goctl/example/rpc/hello/etc/hello.yaml
new file mode 100644
index 00000000..91d30bb5
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/etc/hello.yaml
@@ -0,0 +1,6 @@
+Name: hello.rpc
+ListenOn: 127.0.0.1:8080
+Etcd:
+ Hosts:
+ - 127.0.0.1:2379
+ Key: hello.rpc
diff --git a/tools/goctl/example/rpc/hello/hello.go b/tools/goctl/example/rpc/hello/hello.go
new file mode 100644
index 00000000..dd92f637
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/hello.go
@@ -0,0 +1,39 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/config"
+ greetServer "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/server/greet"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/pb/hello"
+
+ "github.com/zeromicro/go-zero/core/conf"
+ "github.com/zeromicro/go-zero/core/service"
+ "github.com/zeromicro/go-zero/zrpc"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/reflection"
+)
+
+var configFile = flag.String("f", "etc/hello.yaml", "the config file")
+
+func main() {
+ flag.Parse()
+
+ var c config.Config
+ conf.MustLoad(*configFile, &c)
+ ctx := svc.NewServiceContext(c)
+
+ s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
+ hello.RegisterGreetServer(grpcServer, greetServer.NewGreetServer(ctx))
+
+ if c.Mode == service.DevMode || c.Mode == service.TestMode {
+ reflection.Register(grpcServer)
+ }
+ })
+ defer s.Stop()
+
+ fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
+ s.Start()
+}
diff --git a/tools/goctl/example/rpc/hello/internal/config/config.go b/tools/goctl/example/rpc/hello/internal/config/config.go
new file mode 100755
index 00000000..c1f85b99
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/internal/config/config.go
@@ -0,0 +1,7 @@
+package config
+
+import "github.com/zeromicro/go-zero/zrpc"
+
+type Config struct {
+ zrpc.RpcServerConf
+}
diff --git a/tools/goctl/example/rpc/hello/internal/logic/greet/sayhellologic.go b/tools/goctl/example/rpc/hello/internal/logic/greet/sayhellologic.go
new file mode 100644
index 00000000..c94994e4
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/internal/logic/greet/sayhellologic.go
@@ -0,0 +1,30 @@
+package greetlogic
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/pb/hello"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type SayHelloLogic struct {
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+ logx.Logger
+}
+
+func NewSayHelloLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SayHelloLogic {
+ return &SayHelloLogic{
+ ctx: ctx,
+ svcCtx: svcCtx,
+ Logger: logx.WithContext(ctx),
+ }
+}
+
+func (l *SayHelloLogic) SayHello(in *hello.HelloReq) (*hello.HelloResp, error) {
+ // todo: add your logic here and delete this line
+
+ return &hello.HelloResp{}, nil
+}
diff --git a/tools/goctl/example/rpc/hello/internal/server/greet/greetserver.go b/tools/goctl/example/rpc/hello/internal/server/greet/greetserver.go
new file mode 100644
index 00000000..f0a4d383
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/internal/server/greet/greetserver.go
@@ -0,0 +1,28 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hello.proto
+
+package server
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/logic/greet"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/pb/hello"
+)
+
+type GreetServer struct {
+ svcCtx *svc.ServiceContext
+ hello.UnimplementedGreetServer
+}
+
+func NewGreetServer(svcCtx *svc.ServiceContext) *GreetServer {
+ return &GreetServer{
+ svcCtx: svcCtx,
+ }
+}
+
+func (s *GreetServer) SayHello(ctx context.Context, in *hello.HelloReq) (*hello.HelloResp, error) {
+ l := greetlogic.NewSayHelloLogic(ctx, s.svcCtx)
+ return l.SayHello(in)
+}
diff --git a/tools/goctl/example/rpc/hello/internal/svc/servicecontext.go b/tools/goctl/example/rpc/hello/internal/svc/servicecontext.go
new file mode 100644
index 00000000..961a318d
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/internal/svc/servicecontext.go
@@ -0,0 +1,13 @@
+package svc
+
+import "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hello/internal/config"
+
+type ServiceContext struct {
+ Config config.Config
+}
+
+func NewServiceContext(c config.Config) *ServiceContext {
+ return &ServiceContext{
+ Config: c,
+ }
+}
diff --git a/tools/goctl/example/rpc/hello/pb/hello/hello.pb.go b/tools/goctl/example/rpc/hello/pb/hello/hello.pb.go
new file mode 100644
index 00000000..3d9e24bd
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/pb/hello/hello.pb.go
@@ -0,0 +1,208 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.0
+// protoc v3.19.4
+// source: hello.proto
+
+package hello
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+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)
+)
+
+type HelloReq struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ In string `protobuf:"bytes,1,opt,name=in,proto3" json:"in,omitempty"`
+}
+
+func (x *HelloReq) Reset() {
+ *x = HelloReq{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hello_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloReq) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloReq) ProtoMessage() {}
+
+func (x *HelloReq) ProtoReflect() protoreflect.Message {
+ mi := &file_hello_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 HelloReq.ProtoReflect.Descriptor instead.
+func (*HelloReq) Descriptor() ([]byte, []int) {
+ return file_hello_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HelloReq) GetIn() string {
+ if x != nil {
+ return x.In
+ }
+ return ""
+}
+
+type HelloResp struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
+}
+
+func (x *HelloResp) Reset() {
+ *x = HelloResp{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hello_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloResp) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloResp) ProtoMessage() {}
+
+func (x *HelloResp) ProtoReflect() protoreflect.Message {
+ mi := &file_hello_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)
+}
+
+// Deprecated: Use HelloResp.ProtoReflect.Descriptor instead.
+func (*HelloResp) Descriptor() ([]byte, []int) {
+ return file_hello_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HelloResp) GetMsg() string {
+ if x != nil {
+ return x.Msg
+ }
+ return ""
+}
+
+var File_hello_proto protoreflect.FileDescriptor
+
+var file_hello_proto_rawDesc = []byte{
+ 0x0a, 0x0b, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x68,
+ 0x65, 0x6c, 0x6c, 0x6f, 0x22, 0x1a, 0x0a, 0x08, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71,
+ 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x6e,
+ 0x22, 0x1d, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a,
+ 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x32,
+ 0x36, 0x0a, 0x05, 0x47, 0x72, 0x65, 0x65, 0x74, 0x12, 0x2d, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48,
+ 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x0f, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x48, 0x65, 0x6c,
+ 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x10, 0x2e, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2e, 0x48, 0x65,
+ 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x68, 0x65, 0x6c,
+ 0x6c, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_hello_proto_rawDescOnce sync.Once
+ file_hello_proto_rawDescData = file_hello_proto_rawDesc
+)
+
+func file_hello_proto_rawDescGZIP() []byte {
+ file_hello_proto_rawDescOnce.Do(func() {
+ file_hello_proto_rawDescData = protoimpl.X.CompressGZIP(file_hello_proto_rawDescData)
+ })
+ return file_hello_proto_rawDescData
+}
+
+var file_hello_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_hello_proto_goTypes = []interface{}{
+ (*HelloReq)(nil), // 0: hello.HelloReq
+ (*HelloResp)(nil), // 1: hello.HelloResp
+}
+var file_hello_proto_depIdxs = []int32{
+ 0, // 0: hello.Greet.SayHello:input_type -> hello.HelloReq
+ 1, // 1: hello.Greet.SayHello:output_type -> hello.HelloResp
+ 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_hello_proto_init() }
+func file_hello_proto_init() {
+ if File_hello_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_hello_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloReq); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hello_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloResp); 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_hello_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 1,
+ },
+ GoTypes: file_hello_proto_goTypes,
+ DependencyIndexes: file_hello_proto_depIdxs,
+ MessageInfos: file_hello_proto_msgTypes,
+ }.Build()
+ File_hello_proto = out.File
+ file_hello_proto_rawDesc = nil
+ file_hello_proto_goTypes = nil
+ file_hello_proto_depIdxs = nil
+}
diff --git a/tools/goctl/example/rpc/hello/pb/hello/hello_grpc.pb.go b/tools/goctl/example/rpc/hello/pb/hello/hello_grpc.pb.go
new file mode 100644
index 00000000..1eb025b2
--- /dev/null
+++ b/tools/goctl/example/rpc/hello/pb/hello/hello_grpc.pb.go
@@ -0,0 +1,105 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc v3.19.4
+// source: hello.proto
+
+package hello
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// GreetClient is the client API for Greet service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type GreetClient interface {
+ SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error)
+}
+
+type greetClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewGreetClient(cc grpc.ClientConnInterface) GreetClient {
+ return &greetClient{cc}
+}
+
+func (c *greetClient) SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
+ out := new(HelloResp)
+ err := c.cc.Invoke(ctx, "/hello.Greet/SayHello", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// GreetServer is the server API for Greet service.
+// All implementations must embed UnimplementedGreetServer
+// for forward compatibility
+type GreetServer interface {
+ SayHello(context.Context, *HelloReq) (*HelloResp, error)
+ mustEmbedUnimplementedGreetServer()
+}
+
+// UnimplementedGreetServer must be embedded to have forward compatible implementations.
+type UnimplementedGreetServer struct {
+}
+
+func (UnimplementedGreetServer) SayHello(context.Context, *HelloReq) (*HelloResp, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
+}
+func (UnimplementedGreetServer) mustEmbedUnimplementedGreetServer() {}
+
+// UnsafeGreetServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to GreetServer will
+// result in compilation errors.
+type UnsafeGreetServer interface {
+ mustEmbedUnimplementedGreetServer()
+}
+
+func RegisterGreetServer(s grpc.ServiceRegistrar, srv GreetServer) {
+ s.RegisterService(&Greet_ServiceDesc, srv)
+}
+
+func _Greet_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HelloReq)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GreetServer).SayHello(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/hello.Greet/SayHello",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GreetServer).SayHello(ctx, req.(*HelloReq))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// Greet_ServiceDesc is the grpc.ServiceDesc for Greet service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Greet_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "hello.Greet",
+ HandlerType: (*GreetServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SayHello",
+ Handler: _Greet_SayHello_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "hello.proto",
+}
diff --git a/tools/goctl/example/rpc/hi.proto b/tools/goctl/example/rpc/hi.proto
new file mode 100644
index 00000000..c75f577c
--- /dev/null
+++ b/tools/goctl/example/rpc/hi.proto
@@ -0,0 +1,33 @@
+syntax = "proto3";
+
+package hi;
+
+option go_package = "./hi";
+
+message HiReq {
+ string in = 1;
+}
+
+message HelloReq {
+ string in = 1;
+}
+
+message HiResp {
+ string msg = 1;
+}
+
+message HelloResp {
+ string msg = 1;
+}
+
+service Greet {
+ rpc SayHi(HiReq) returns (HiResp);
+ rpc SayHello(HelloReq) returns (HelloResp);
+}
+
+message EventReq{}
+message EventResp{}
+
+service Event {
+ rpc AskQuestion(EventReq) returns (EventResp);
+}
\ No newline at end of file
diff --git a/tools/goctl/example/rpc/hi/client/event/event.go b/tools/goctl/example/rpc/hi/client/event/event.go
new file mode 100644
index 00000000..7a346baa
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/client/event/event.go
@@ -0,0 +1,41 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hi.proto
+
+package client
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/zrpc"
+ "google.golang.org/grpc"
+)
+
+type (
+ EventReq = hi.EventReq
+ EventResp = hi.EventResp
+ HelloReq = hi.HelloReq
+ HelloResp = hi.HelloResp
+ HiReq = hi.HiReq
+ HiResp = hi.HiResp
+
+ Event interface {
+ AskQuestion(ctx context.Context, in *EventReq, opts ...grpc.CallOption) (*EventResp, error)
+ }
+
+ defaultEvent struct {
+ cli zrpc.Client
+ }
+)
+
+func NewEvent(cli zrpc.Client) Event {
+ return &defaultEvent{
+ cli: cli,
+ }
+}
+
+func (m *defaultEvent) AskQuestion(ctx context.Context, in *EventReq, opts ...grpc.CallOption) (*EventResp, error) {
+ client := hi.NewEventClient(m.cli.Conn())
+ return client.AskQuestion(ctx, in, opts...)
+}
diff --git a/tools/goctl/example/rpc/hi/client/greet/greet.go b/tools/goctl/example/rpc/hi/client/greet/greet.go
new file mode 100644
index 00000000..3c0b15b6
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/client/greet/greet.go
@@ -0,0 +1,47 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hi.proto
+
+package client
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/zrpc"
+ "google.golang.org/grpc"
+)
+
+type (
+ EventReq = hi.EventReq
+ EventResp = hi.EventResp
+ HelloReq = hi.HelloReq
+ HelloResp = hi.HelloResp
+ HiReq = hi.HiReq
+ HiResp = hi.HiResp
+
+ Greet interface {
+ SayHi(ctx context.Context, in *HiReq, opts ...grpc.CallOption) (*HiResp, error)
+ SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error)
+ }
+
+ defaultGreet struct {
+ cli zrpc.Client
+ }
+)
+
+func NewGreet(cli zrpc.Client) Greet {
+ return &defaultGreet{
+ cli: cli,
+ }
+}
+
+func (m *defaultGreet) SayHi(ctx context.Context, in *HiReq, opts ...grpc.CallOption) (*HiResp, error) {
+ client := hi.NewGreetClient(m.cli.Conn())
+ return client.SayHi(ctx, in, opts...)
+}
+
+func (m *defaultGreet) SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
+ client := hi.NewGreetClient(m.cli.Conn())
+ return client.SayHello(ctx, in, opts...)
+}
diff --git a/tools/goctl/example/rpc/hi/etc/hi.yaml b/tools/goctl/example/rpc/hi/etc/hi.yaml
new file mode 100644
index 00000000..ad1c8375
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/etc/hi.yaml
@@ -0,0 +1,6 @@
+Name: hi.rpc
+ListenOn: 127.0.0.1:8080
+Etcd:
+ Hosts:
+ - 127.0.0.1:2379
+ Key: hi.rpc
diff --git a/tools/goctl/example/rpc/hi/hi.go b/tools/goctl/example/rpc/hi/hi.go
new file mode 100644
index 00000000..9e6cc0d0
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/hi.go
@@ -0,0 +1,41 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/config"
+ eventServer "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/server/event"
+ greetServer "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/server/greet"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/core/conf"
+ "github.com/zeromicro/go-zero/core/service"
+ "github.com/zeromicro/go-zero/zrpc"
+ "google.golang.org/grpc"
+ "google.golang.org/grpc/reflection"
+)
+
+var configFile = flag.String("f", "etc/hi.yaml", "the config file")
+
+func main() {
+ flag.Parse()
+
+ var c config.Config
+ conf.MustLoad(*configFile, &c)
+ ctx := svc.NewServiceContext(c)
+
+ s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
+ hi.RegisterGreetServer(grpcServer, greetServer.NewGreetServer(ctx))
+ hi.RegisterEventServer(grpcServer, eventServer.NewEventServer(ctx))
+
+ if c.Mode == service.DevMode || c.Mode == service.TestMode {
+ reflection.Register(grpcServer)
+ }
+ })
+ defer s.Stop()
+
+ fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
+ s.Start()
+}
diff --git a/tools/goctl/example/rpc/hi/internal/config/config.go b/tools/goctl/example/rpc/hi/internal/config/config.go
new file mode 100755
index 00000000..c1f85b99
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/config/config.go
@@ -0,0 +1,7 @@
+package config
+
+import "github.com/zeromicro/go-zero/zrpc"
+
+type Config struct {
+ zrpc.RpcServerConf
+}
diff --git a/tools/goctl/example/rpc/hi/internal/logic/event/askquestionlogic.go b/tools/goctl/example/rpc/hi/internal/logic/event/askquestionlogic.go
new file mode 100644
index 00000000..697ade52
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/logic/event/askquestionlogic.go
@@ -0,0 +1,30 @@
+package eventlogic
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type AskQuestionLogic struct {
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+ logx.Logger
+}
+
+func NewAskQuestionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AskQuestionLogic {
+ return &AskQuestionLogic{
+ ctx: ctx,
+ svcCtx: svcCtx,
+ Logger: logx.WithContext(ctx),
+ }
+}
+
+func (l *AskQuestionLogic) AskQuestion(in *hi.EventReq) (*hi.EventResp, error) {
+ // todo: add your logic here and delete this line
+
+ return &hi.EventResp{}, nil
+}
diff --git a/tools/goctl/example/rpc/hi/internal/logic/greet/sayhellologic.go b/tools/goctl/example/rpc/hi/internal/logic/greet/sayhellologic.go
new file mode 100644
index 00000000..51dec93a
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/logic/greet/sayhellologic.go
@@ -0,0 +1,30 @@
+package greetlogic
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type SayHelloLogic struct {
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+ logx.Logger
+}
+
+func NewSayHelloLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SayHelloLogic {
+ return &SayHelloLogic{
+ ctx: ctx,
+ svcCtx: svcCtx,
+ Logger: logx.WithContext(ctx),
+ }
+}
+
+func (l *SayHelloLogic) SayHello(in *hi.HelloReq) (*hi.HelloResp, error) {
+ // todo: add your logic here and delete this line
+
+ return &hi.HelloResp{}, nil
+}
diff --git a/tools/goctl/example/rpc/hi/internal/logic/greet/sayhilogic.go b/tools/goctl/example/rpc/hi/internal/logic/greet/sayhilogic.go
new file mode 100644
index 00000000..80c08fcb
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/logic/greet/sayhilogic.go
@@ -0,0 +1,30 @@
+package greetlogic
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+
+ "github.com/zeromicro/go-zero/core/logx"
+)
+
+type SayHiLogic struct {
+ ctx context.Context
+ svcCtx *svc.ServiceContext
+ logx.Logger
+}
+
+func NewSayHiLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SayHiLogic {
+ return &SayHiLogic{
+ ctx: ctx,
+ svcCtx: svcCtx,
+ Logger: logx.WithContext(ctx),
+ }
+}
+
+func (l *SayHiLogic) SayHi(in *hi.HiReq) (*hi.HiResp, error) {
+ // todo: add your logic here and delete this line
+
+ return &hi.HiResp{}, nil
+}
diff --git a/tools/goctl/example/rpc/hi/internal/server/event/eventserver.go b/tools/goctl/example/rpc/hi/internal/server/event/eventserver.go
new file mode 100644
index 00000000..ac89b0c6
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/server/event/eventserver.go
@@ -0,0 +1,28 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hi.proto
+
+package server
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/logic/event"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+)
+
+type EventServer struct {
+ svcCtx *svc.ServiceContext
+ hi.UnimplementedEventServer
+}
+
+func NewEventServer(svcCtx *svc.ServiceContext) *EventServer {
+ return &EventServer{
+ svcCtx: svcCtx,
+ }
+}
+
+func (s *EventServer) AskQuestion(ctx context.Context, in *hi.EventReq) (*hi.EventResp, error) {
+ l := eventlogic.NewAskQuestionLogic(ctx, s.svcCtx)
+ return l.AskQuestion(in)
+}
diff --git a/tools/goctl/example/rpc/hi/internal/server/greet/greetserver.go b/tools/goctl/example/rpc/hi/internal/server/greet/greetserver.go
new file mode 100644
index 00000000..4308e1fa
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/server/greet/greetserver.go
@@ -0,0 +1,33 @@
+// Code generated by goctl. DO NOT EDIT!
+// Source: hi.proto
+
+package server
+
+import (
+ "context"
+
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/logic/greet"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/svc"
+ "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/pb/hi"
+)
+
+type GreetServer struct {
+ svcCtx *svc.ServiceContext
+ hi.UnimplementedGreetServer
+}
+
+func NewGreetServer(svcCtx *svc.ServiceContext) *GreetServer {
+ return &GreetServer{
+ svcCtx: svcCtx,
+ }
+}
+
+func (s *GreetServer) SayHi(ctx context.Context, in *hi.HiReq) (*hi.HiResp, error) {
+ l := greetlogic.NewSayHiLogic(ctx, s.svcCtx)
+ return l.SayHi(in)
+}
+
+func (s *GreetServer) SayHello(ctx context.Context, in *hi.HelloReq) (*hi.HelloResp, error) {
+ l := greetlogic.NewSayHelloLogic(ctx, s.svcCtx)
+ return l.SayHello(in)
+}
diff --git a/tools/goctl/example/rpc/hi/internal/svc/servicecontext.go b/tools/goctl/example/rpc/hi/internal/svc/servicecontext.go
new file mode 100644
index 00000000..fe4af36e
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/internal/svc/servicecontext.go
@@ -0,0 +1,13 @@
+package svc
+
+import "github.com/zeromicro/go-zero/tools/goctl/example/rpc/hi/internal/config"
+
+type ServiceContext struct {
+ Config config.Config
+}
+
+func NewServiceContext(c config.Config) *ServiceContext {
+ return &ServiceContext{
+ Config: c,
+ }
+}
diff --git a/tools/goctl/example/rpc/hi/pb/hi/hi.pb.go b/tools/goctl/example/rpc/hi/pb/hi/hi.pb.go
new file mode 100644
index 00000000..d523fb1a
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/pb/hi/hi.pb.go
@@ -0,0 +1,443 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.28.0
+// protoc v3.19.4
+// source: hi.proto
+
+package hi
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+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)
+)
+
+type HiReq struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ In string `protobuf:"bytes,1,opt,name=in,proto3" json:"in,omitempty"`
+}
+
+func (x *HiReq) Reset() {
+ *x = HiReq{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HiReq) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HiReq) ProtoMessage() {}
+
+func (x *HiReq) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_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 HiReq.ProtoReflect.Descriptor instead.
+func (*HiReq) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *HiReq) GetIn() string {
+ if x != nil {
+ return x.In
+ }
+ return ""
+}
+
+type HelloReq struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ In string `protobuf:"bytes,1,opt,name=in,proto3" json:"in,omitempty"`
+}
+
+func (x *HelloReq) Reset() {
+ *x = HelloReq{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloReq) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloReq) ProtoMessage() {}
+
+func (x *HelloReq) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_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)
+}
+
+// Deprecated: Use HelloReq.ProtoReflect.Descriptor instead.
+func (*HelloReq) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *HelloReq) GetIn() string {
+ if x != nil {
+ return x.In
+ }
+ return ""
+}
+
+type HiResp struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
+}
+
+func (x *HiResp) Reset() {
+ *x = HiResp{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[2]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HiResp) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HiResp) ProtoMessage() {}
+
+func (x *HiResp) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_proto_msgTypes[2]
+ 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 HiResp.ProtoReflect.Descriptor instead.
+func (*HiResp) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *HiResp) GetMsg() string {
+ if x != nil {
+ return x.Msg
+ }
+ return ""
+}
+
+type HelloResp struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Msg string `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"`
+}
+
+func (x *HelloResp) Reset() {
+ *x = HelloResp{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[3]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *HelloResp) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*HelloResp) ProtoMessage() {}
+
+func (x *HelloResp) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_proto_msgTypes[3]
+ 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 HelloResp.ProtoReflect.Descriptor instead.
+func (*HelloResp) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *HelloResp) GetMsg() string {
+ if x != nil {
+ return x.Msg
+ }
+ return ""
+}
+
+type EventReq struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *EventReq) Reset() {
+ *x = EventReq{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EventReq) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EventReq) ProtoMessage() {}
+
+func (x *EventReq) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_proto_msgTypes[4]
+ 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 EventReq.ProtoReflect.Descriptor instead.
+func (*EventReq) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{4}
+}
+
+type EventResp struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+}
+
+func (x *EventResp) Reset() {
+ *x = EventResp{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_hi_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *EventResp) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*EventResp) ProtoMessage() {}
+
+func (x *EventResp) ProtoReflect() protoreflect.Message {
+ mi := &file_hi_proto_msgTypes[5]
+ 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 EventResp.ProtoReflect.Descriptor instead.
+func (*EventResp) Descriptor() ([]byte, []int) {
+ return file_hi_proto_rawDescGZIP(), []int{5}
+}
+
+var File_hi_proto protoreflect.FileDescriptor
+
+var file_hi_proto_rawDesc = []byte{
+ 0x0a, 0x08, 0x68, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x02, 0x68, 0x69, 0x22, 0x17,
+ 0x0a, 0x05, 0x48, 0x69, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x6e, 0x22, 0x1a, 0x0a, 0x08, 0x48, 0x65, 0x6c, 0x6c, 0x6f,
+ 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x02, 0x69, 0x6e, 0x22, 0x1a, 0x0a, 0x06, 0x48, 0x69, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a,
+ 0x03, 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22,
+ 0x1d, 0x0a, 0x09, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x12, 0x10, 0x0a, 0x03,
+ 0x6d, 0x73, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x73, 0x67, 0x22, 0x0a,
+ 0x0a, 0x08, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x22, 0x0b, 0x0a, 0x09, 0x45, 0x76,
+ 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x32, 0x50, 0x0a, 0x05, 0x47, 0x72, 0x65, 0x65, 0x74,
+ 0x12, 0x1e, 0x0a, 0x05, 0x53, 0x61, 0x79, 0x48, 0x69, 0x12, 0x09, 0x2e, 0x68, 0x69, 0x2e, 0x48,
+ 0x69, 0x52, 0x65, 0x71, 0x1a, 0x0a, 0x2e, 0x68, 0x69, 0x2e, 0x48, 0x69, 0x52, 0x65, 0x73, 0x70,
+ 0x12, 0x27, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, 0x0c, 0x2e, 0x68,
+ 0x69, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x68, 0x69, 0x2e,
+ 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x32, 0x33, 0x0a, 0x05, 0x45, 0x76, 0x65,
+ 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x0b, 0x41, 0x73, 0x6b, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f,
+ 0x6e, 0x12, 0x0c, 0x2e, 0x68, 0x69, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a,
+ 0x0d, 0x2e, 0x68, 0x69, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x42, 0x06,
+ 0x5a, 0x04, 0x2e, 0x2f, 0x68, 0x69, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+ file_hi_proto_rawDescOnce sync.Once
+ file_hi_proto_rawDescData = file_hi_proto_rawDesc
+)
+
+func file_hi_proto_rawDescGZIP() []byte {
+ file_hi_proto_rawDescOnce.Do(func() {
+ file_hi_proto_rawDescData = protoimpl.X.CompressGZIP(file_hi_proto_rawDescData)
+ })
+ return file_hi_proto_rawDescData
+}
+
+var file_hi_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
+var file_hi_proto_goTypes = []interface{}{
+ (*HiReq)(nil), // 0: hi.HiReq
+ (*HelloReq)(nil), // 1: hi.HelloReq
+ (*HiResp)(nil), // 2: hi.HiResp
+ (*HelloResp)(nil), // 3: hi.HelloResp
+ (*EventReq)(nil), // 4: hi.EventReq
+ (*EventResp)(nil), // 5: hi.EventResp
+}
+var file_hi_proto_depIdxs = []int32{
+ 0, // 0: hi.Greet.SayHi:input_type -> hi.HiReq
+ 1, // 1: hi.Greet.SayHello:input_type -> hi.HelloReq
+ 4, // 2: hi.Event.AskQuestion:input_type -> hi.EventReq
+ 2, // 3: hi.Greet.SayHi:output_type -> hi.HiResp
+ 3, // 4: hi.Greet.SayHello:output_type -> hi.HelloResp
+ 5, // 5: hi.Event.AskQuestion:output_type -> hi.EventResp
+ 3, // [3:6] is the sub-list for method output_type
+ 0, // [0:3] 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_hi_proto_init() }
+func file_hi_proto_init() {
+ if File_hi_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_hi_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HiReq); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hi_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloReq); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hi_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HiResp); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hi_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*HelloResp); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hi_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EventReq); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_hi_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*EventResp); 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_hi_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 6,
+ NumExtensions: 0,
+ NumServices: 2,
+ },
+ GoTypes: file_hi_proto_goTypes,
+ DependencyIndexes: file_hi_proto_depIdxs,
+ MessageInfos: file_hi_proto_msgTypes,
+ }.Build()
+ File_hi_proto = out.File
+ file_hi_proto_rawDesc = nil
+ file_hi_proto_goTypes = nil
+ file_hi_proto_depIdxs = nil
+}
diff --git a/tools/goctl/example/rpc/hi/pb/hi/hi_grpc.pb.go b/tools/goctl/example/rpc/hi/pb/hi/hi_grpc.pb.go
new file mode 100644
index 00000000..62c20326
--- /dev/null
+++ b/tools/goctl/example/rpc/hi/pb/hi/hi_grpc.pb.go
@@ -0,0 +1,227 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.2.0
+// - protoc v3.19.4
+// source: hi.proto
+
+package hi
+
+import (
+ context "context"
+ grpc "google.golang.org/grpc"
+ codes "google.golang.org/grpc/codes"
+ status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.32.0 or later.
+const _ = grpc.SupportPackageIsVersion7
+
+// GreetClient is the client API for Greet service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type GreetClient interface {
+ SayHi(ctx context.Context, in *HiReq, opts ...grpc.CallOption) (*HiResp, error)
+ SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error)
+}
+
+type greetClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewGreetClient(cc grpc.ClientConnInterface) GreetClient {
+ return &greetClient{cc}
+}
+
+func (c *greetClient) SayHi(ctx context.Context, in *HiReq, opts ...grpc.CallOption) (*HiResp, error) {
+ out := new(HiResp)
+ err := c.cc.Invoke(ctx, "/hi.Greet/SayHi", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *greetClient) SayHello(ctx context.Context, in *HelloReq, opts ...grpc.CallOption) (*HelloResp, error) {
+ out := new(HelloResp)
+ err := c.cc.Invoke(ctx, "/hi.Greet/SayHello", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// GreetServer is the server API for Greet service.
+// All implementations must embed UnimplementedGreetServer
+// for forward compatibility
+type GreetServer interface {
+ SayHi(context.Context, *HiReq) (*HiResp, error)
+ SayHello(context.Context, *HelloReq) (*HelloResp, error)
+ mustEmbedUnimplementedGreetServer()
+}
+
+// UnimplementedGreetServer must be embedded to have forward compatible implementations.
+type UnimplementedGreetServer struct {
+}
+
+func (UnimplementedGreetServer) SayHi(context.Context, *HiReq) (*HiResp, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SayHi not implemented")
+}
+func (UnimplementedGreetServer) SayHello(context.Context, *HelloReq) (*HelloResp, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented")
+}
+func (UnimplementedGreetServer) mustEmbedUnimplementedGreetServer() {}
+
+// UnsafeGreetServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to GreetServer will
+// result in compilation errors.
+type UnsafeGreetServer interface {
+ mustEmbedUnimplementedGreetServer()
+}
+
+func RegisterGreetServer(s grpc.ServiceRegistrar, srv GreetServer) {
+ s.RegisterService(&Greet_ServiceDesc, srv)
+}
+
+func _Greet_SayHi_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HiReq)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GreetServer).SayHi(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/hi.Greet/SayHi",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GreetServer).SayHi(ctx, req.(*HiReq))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _Greet_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(HelloReq)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GreetServer).SayHello(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/hi.Greet/SayHello",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GreetServer).SayHello(ctx, req.(*HelloReq))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// Greet_ServiceDesc is the grpc.ServiceDesc for Greet service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Greet_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "hi.Greet",
+ HandlerType: (*GreetServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "SayHi",
+ Handler: _Greet_SayHi_Handler,
+ },
+ {
+ MethodName: "SayHello",
+ Handler: _Greet_SayHello_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "hi.proto",
+}
+
+// EventClient is the client API for Event service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type EventClient interface {
+ AskQuestion(ctx context.Context, in *EventReq, opts ...grpc.CallOption) (*EventResp, error)
+}
+
+type eventClient struct {
+ cc grpc.ClientConnInterface
+}
+
+func NewEventClient(cc grpc.ClientConnInterface) EventClient {
+ return &eventClient{cc}
+}
+
+func (c *eventClient) AskQuestion(ctx context.Context, in *EventReq, opts ...grpc.CallOption) (*EventResp, error) {
+ out := new(EventResp)
+ err := c.cc.Invoke(ctx, "/hi.Event/AskQuestion", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+// EventServer is the server API for Event service.
+// All implementations must embed UnimplementedEventServer
+// for forward compatibility
+type EventServer interface {
+ AskQuestion(context.Context, *EventReq) (*EventResp, error)
+ mustEmbedUnimplementedEventServer()
+}
+
+// UnimplementedEventServer must be embedded to have forward compatible implementations.
+type UnimplementedEventServer struct {
+}
+
+func (UnimplementedEventServer) AskQuestion(context.Context, *EventReq) (*EventResp, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method AskQuestion not implemented")
+}
+func (UnimplementedEventServer) mustEmbedUnimplementedEventServer() {}
+
+// UnsafeEventServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to EventServer will
+// result in compilation errors.
+type UnsafeEventServer interface {
+ mustEmbedUnimplementedEventServer()
+}
+
+func RegisterEventServer(s grpc.ServiceRegistrar, srv EventServer) {
+ s.RegisterService(&Event_ServiceDesc, srv)
+}
+
+func _Event_AskQuestion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(EventReq)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(EventServer).AskQuestion(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/hi.Event/AskQuestion",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(EventServer).AskQuestion(ctx, req.(*EventReq))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+// Event_ServiceDesc is the grpc.ServiceDesc for Event service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var Event_ServiceDesc = grpc.ServiceDesc{
+ ServiceName: "hi.Event",
+ HandlerType: (*EventServer)(nil),
+ Methods: []grpc.MethodDesc{
+ {
+ MethodName: "AskQuestion",
+ Handler: _Event_AskQuestion_Handler,
+ },
+ },
+ Streams: []grpc.StreamDesc{},
+ Metadata: "hi.proto",
+}
diff --git a/tools/goctl/example/rpc/multiple_rpc_service_generate.sh b/tools/goctl/example/rpc/multiple_rpc_service_generate.sh
new file mode 100644
index 00000000..a0cdf99c
--- /dev/null
+++ b/tools/goctl/example/rpc/multiple_rpc_service_generate.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+wd=$(pwd)
+output="$wd/hi"
+
+rm -rf $output
+
+goctl rpc protoc -I $wd "$wd/hi.proto" --go_out="$output/pb" --go-grpc_out="$output/pb" --zrpc_out="$output" --multiple
+
+if [ $? -ne 0 ]; then
+ echo "Generate failed"
+ exit 1
+fi
+
+GOPROXY="https://goproxy.cn,direct" && go mod tidy
+
+if [ $? -ne 0 ]; then
+ echo "Tidy failed"
+ exit 1
+fi
+
+go test ./...
\ No newline at end of file
diff --git a/tools/goctl/example/rpc/single_rpc_service_generate.sh b/tools/goctl/example/rpc/single_rpc_service_generate.sh
new file mode 100644
index 00000000..4c4717de
--- /dev/null
+++ b/tools/goctl/example/rpc/single_rpc_service_generate.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+wd=$(pwd)
+output="$wd/hello"
+
+rm -rf $output
+
+goctl rpc protoc -I $wd "$wd/hello.proto" --go_out="$output/pb" --go-grpc_out="$output/pb" --zrpc_out="$output" --multiple
+
+if [ $? -ne 0 ]; then
+ echo "Generate failed"
+ exit 1
+fi
+
+GOPROXY="https://goproxy.cn,direct" && go mod tidy
+
+if [ $? -ne 0 ]; then
+ echo "Tidy failed"
+ exit 1
+fi
+
+go test ./...
\ No newline at end of file
diff --git a/tools/goctl/go.mod b/tools/goctl/go.mod
index 8d822916..01907f88 100644
--- a/tools/goctl/go.mod
+++ b/tools/goctl/go.mod
@@ -11,8 +11,10 @@ require (
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/spf13/cobra v1.4.0
github.com/stretchr/testify v1.7.1
- github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220612192618-e5d7d8e71f63
+ github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220705165518-2761d7f4b8bc
github.com/zeromicro/antlr v0.0.1
github.com/zeromicro/ddl-parser v1.0.4
github.com/zeromicro/go-zero v1.3.4
+ google.golang.org/grpc v1.46.2
+ google.golang.org/protobuf v1.28.0
)
diff --git a/tools/goctl/go.sum b/tools/goctl/go.sum
index 32089ba0..afb9f823 100644
--- a/tools/goctl/go.sum
+++ b/tools/goctl/go.sum
@@ -85,6 +85,7 @@ github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
+github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
@@ -116,7 +117,9 @@ github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
@@ -194,6 +197,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -209,6 +213,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -250,6 +255,7 @@ github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -273,12 +279,14 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU=
+github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw=
github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
@@ -342,6 +350,7 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
@@ -403,9 +412,11 @@ github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
@@ -449,6 +460,7 @@ github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -535,8 +547,8 @@ github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYa
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
-github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220612192618-e5d7d8e71f63 h1:fh1HoAQAIFTWjlmOQ/vjHHe6H22n2bnzYHX6R0JQE3c=
-github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220612192618-e5d7d8e71f63/go.mod h1:nmuySobZb4kFgFy6BptpXp/BBw+xFSyvVPP6auoJB4k=
+github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220705165518-2761d7f4b8bc h1:2pGkMttK5jQ8+6YhdyeQIHyVa84HMdJhILozImSWX6c=
+github.com/withfig/autocomplete-tools/integrations/cobra v0.0.0-20220705165518-2761d7f4b8bc/go.mod h1:nmuySobZb4kFgFy6BptpXp/BBw+xFSyvVPP6auoJB4k=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
@@ -555,10 +567,13 @@ github.com/zeromicro/ddl-parser v1.0.4/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiH
github.com/zeromicro/go-zero v1.3.4 h1:XeNdwcrOmnvHj891AmeCA9RrRj1PeN49//KKCK4WAXk=
github.com/zeromicro/go-zero v1.3.4/go.mod h1:nEU/ITZSmxRxvr/JmSoJ48MNV62UpY6bqJz9Voba7Yw=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
+go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
+go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -580,14 +595,18 @@ go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJ
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk=
go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
+go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
@@ -706,6 +725,7 @@ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -805,6 +825,7 @@ golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
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=
@@ -820,6 +841,7 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
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=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -920,6 +942,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
@@ -1046,6 +1069,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
@@ -1070,12 +1094,16 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+k8s.io/api v0.22.9 h1:PidjRtgd0zDa6SvyooBLH/SP62uOhEBY0kx0UYRGr1o=
k8s.io/api v0.22.9/go.mod h1:rcjO/FPOuvc3x7nQWx29UcDrFJMx82RxDob71ntNH4A=
+k8s.io/apimachinery v0.22.9 h1:5qjnpBk6eC9me0SAzokCUMI0KVF2PENK1PnykF8/Gjo=
k8s.io/apimachinery v0.22.9/go.mod h1:ZvVLP5iLhwVFg2Yx9Gh5W0um0DUauExbRhe+2Z8I1EU=
+k8s.io/client-go v0.22.9 h1:5p2R2LsoBfaE6QnXfWFmyyvxrFXtfegUGRMZSpTI+Q8=
k8s.io/client-go v0.22.9/go.mod h1:IoH7exYnoH/zgvHOuVxh2c4yJepcCBt72FzCTisOc4k=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
+k8s.io/klog/v2 v2.40.1 h1:P4RRucWk/lFOlDdkAr3mc7iWFkgKrZY9qZMAgek06S4=
k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20211109043538-20434351676c/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
@@ -1085,5 +1113,7 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
+sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
+sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
diff --git a/tools/goctl/rpc/README.md b/tools/goctl/rpc/README.md
index 8a006ff5..2394fbd1 100644
--- a/tools/goctl/rpc/README.md
+++ b/tools/goctl/rpc/README.md
@@ -7,7 +7,7 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
* 简单易用
* 快速提升开发效率
* 出错率低
-* 贴近protoc
+* 贴近 protoc
## 快速开始
@@ -24,168 +24,41 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
执行后代码结构如下:
- ```golang
+```text
.
-├── etc // yaml配置文件
-│ └── greet.yaml
-├── go.mod
-├── greet // pb.go文件夹①
-│ └── greet.pb.go
-├── greet.go // main函数
-├── greet.proto // proto 文件
-├── greetclient // call logic ②
-│ └── greet.go
-└── internal
- ├── config // yaml配置对应的实体
- │ └── config.go
- ├── logic // 业务代码
- │ └── pinglogic.go
- ├── server // rpc server
- │ └── greetserver.go
- └── svc // 依赖资源
- └── servicecontext.go
- ```
-
-> ① pb文件夹名(老版本文件夹固定为pb)称取自于proto文件中option go_package的值最后一层级按照一定格式进行转换,若无此声明,则取自于package的值,大致代码如下:
-
-```go
- if option.Name == "go_package" {
- ret.GoPackage = option.Constant.Source
- }
- ...
- if len(ret.GoPackage) == 0 {
- ret.GoPackage = ret.Package.Name
- }
- ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
- ...
+└── greet
+ ├── etc
+ │ └── greet.yaml
+ ├── greet
+ │ ├── greet.go
+ │ ├── greet.pb.go
+ │ └── greet_grpc.pb.go
+ ├── greet.go
+ ├── greet.proto
+ └── internal
+ ├── config
+ │ └── config.go
+ ├── logic
+ │ └── pinglogic.go
+ ├── server
+ │ └── greetserver.go
+ └── svc
+ └── servicecontext.go
```
-> GoSanitized方法请参考google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
-
-> ② call 层文件夹名称取自于proto中service的名称,如该sercice的名称和pb文件夹名称相等,则会在srervice后面补充client进行区分,使pb和call分隔。
-
-```go
-if strings.ToLower(proto.Service.Name) == strings.ToLower(proto.GoPackage) {
- callDir = filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name+"_client").ToCamel()))
-}
-```
-
-rpc一键生成常见问题解决,见 常见问题解决
### 方式二:通过指定proto生成rpc服务
* 生成proto模板
- ```Bash
- goctl rpc template -o=user.proto
- ```
-
- ```golang
- syntax = "proto3";
-
- package remote;
-
- message Request {
- // 用户名
- string username = 1;
- // 用户密码
- string password = 2;
- }
-
- message Response {
- // 用户名称
- string name = 1;
- // 用户性别
- string gender = 2;
- }
-
- service User {
- // 登录
- rpc Login(Request)returns(Response);
- }
- ```
-
-* 生成rpc服务代码
-
- ```Bash
- goctl rpc proto -src=user.proto
- ```
-
-## 准备工作
-
-* 安装了go环境
-* 安装了protoc&protoc-gen-go,并且已经设置环境变量
-* 更多问题请见 注意事项
-
-## 用法
-
-### rpc服务生成用法
-
```Bash
-goctl rpc proto -h
+$ goctl rpc template -o=user.proto
```
-
-```Bash
-NAME:
- goctl rpc proto - generate rpc from proto
-
-USAGE:
- goctl rpc proto [command options] [arguments...]
-
-OPTIONS:
- --src value, -s value the file path of the proto source file
- --proto_path value, -I value native command of protoc, specify the directory in which to search for imports. [optional]
- --go_opt value native command of protoc-gen-go, specify the mapping from proto to go, eg --go_opt=proto_import=go_package_import. [optional]
- --dir value, -d value the target path of the code
- --style value the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
- --idea whether the command execution environment is from idea plugin. [optional]
-
-```
-
-### 参数说明
-
-* --src 必填,proto数据源,目前暂时支持单个proto文件生成
-* --proto_path 可选,protoc原生子命令,用于指定proto import从何处查找,可指定多个路径,如`goctl rpc -I={path1} -I={path2} ...`
- ,在没有import时可不填。当前proto路径不用指定,已经内置,`-I`的详细用法请参考`protoc -h`
-* --go_opt 可选,protoc-gen-go插件原生flag,用于指定go_package
-* --dir 可选,默认为proto文件所在目录,生成代码的目标目录
-* --style 可选,指定生成文件名的命名风格
-* --idea 可选,是否为idea插件中执行,终端执行可以忽略
-
-
-### 开发人员需要做什么
-
-关注业务代码编写,将重复性、与业务无关的工作交给goctl,生成好rpc服务代码后,开发人员仅需要修改
-
-* 服务中的配置文件编写(etc/xx.json、internal/config/config.go)
-* 服务中业务逻辑编写(internal/logic/xxlogic.go)
-* 服务中资源上下文的编写(internal/svc/servicecontext.go)
-
-
-### 注意事项
-
-* proto不支持暂多文件同时生成
-* proto不支持外部依赖包引入,message不支持inline
-* 目前main文件、shared文件、handler文件会被强制覆盖,而和开发人员手动需要编写的则不会覆盖生成,这一类在代码头部均有
-
-```shell script
- // Code generated by goctl. DO NOT EDIT!
- // Source: xxx.proto
-```
-
-的标识,请注意不要将也写业务性代码写在里面。
-
-## proto import
-* 对于rpc中的requestType和returnType必须在main proto文件定义,对于proto中的message可以像protoc一样import其他proto文件。
-
-proto示例:
-
-### 错误import
+
```proto
syntax = "proto3";
-package greet;
-
-import "base/common.proto"
+package user;
+option go_package="./user";
message Request {
string ping = 1;
@@ -195,40 +68,136 @@ message Response {
string pong = 1;
}
-service Greet {
- rpc Ping(base.In) returns(base.Out);// request和return 不支持import
-}
-
-```
-
-
-### 正确import
-```proto
-syntax = "proto3";
-
-package greet;
-
-import "base/common.proto"
-
-message Request {
- base.In in = 1;// 支持import
-}
-
-message Response {
- base.Out out = 2;// 支持import
-}
-
-service Greet {
+service User {
rpc Ping(Request) returns(Response);
}
```
+
-## 常见问题解决(go mod工程)
+* 生成rpc服务代码
-* 错误一:
-```text
-A required privilege is not held by the client.
+```bash
+$ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
```
-这个问题只有goctl 版本在`goctl.exe version 1.2.1` 以后的 Windows操作系统出现,主要原因是goctl需要以管理员身份运行,这样才能将`goctl.exe` 创建一个 `ptocot-gen-gcotl`
-的符号链接。
+
+## 用法
+
+### rpc 服务生成用法
+
+```Bash
+$ goctl rpc protoc -h
+Generate grpc code
+
+Usage:
+ goctl rpc protoc [flags]
+
+Examples:
+goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
+
+Flags:
+ --branch string The branch of the remote repo, it does work with --remote
+ -h, --help help for protoc
+ --home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
+ -m, --multiple Generated in multiple rpc service mode
+ --remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
+ The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
+ --style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
+ -v, --verbose Enable log output
+ --zrpc_out string The zrpc output directory
+```
+
+### 参数说明
+
+* --branch 指定远程仓库模板分支
+* --home 指定goctl模板根目录
+* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。
+* --style 指定文件输出格式
+* -v, --verbose 显示日志
+* --zrpc_out 指定zrpc输出目录
+
+> ## --multiple
+> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
+> 1. 支持 1 到多个 rpc service
+> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service)
+> 3. rpc client 的文件目录变更为固定名称 `client`
+>
+> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
+> 1. 有且只能有一个 rpc service
+
+
+## rpc 服务生成 example
+详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)
+
+## --multiple 为 true 和 false 的目录区别
+源 proto 文件
+
+```protobuf
+syntax = "proto3";
+
+package hello;
+
+option go_package = "./hello";
+
+message HelloReq {
+ string in = 1;
+}
+
+message HelloResp {
+ string msg = 1;
+}
+
+service Greet {
+ rpc SayHello(HelloReq) returns (HelloResp);
+}
+```
+
+### --multiple=true
+
+```text
+hello
+├── client // 区别1:rpc client 目录固定为 client 名称
+│ └── greet // 区别2:会按照 rpc service 名称分组
+│ └── greet.go
+├── etc
+│ └── hello.yaml
+├── hello.go
+├── internal
+│ ├── config
+│ │ └── config.go
+│ ├── logic
+│ │ └── greet // 区别2:会按照 rpc service 名称分组
+│ │ └── sayhellologic.go
+│ ├── server
+│ │ └── greet // 区别2:会按照 rpc service 名称分组
+│ │ └── greetserver.go
+│ └── svc
+│ └── servicecontext.go
+└── pb
+ └── hello
+ ├── hello.pb.go
+ └── hello_grpc.pb.go
+```
+
+### --multiple=false (旧版本目录,向后兼容)
+```text
+hello
+├── etc
+│ └── hello.yaml
+├── greet
+│ └── greet.go
+├── hello.go
+├── internal
+│ ├── config
+│ │ └── config.go
+│ ├── logic
+│ │ └── sayhellologic.go
+│ ├── server
+│ │ └── greetserver.go
+│ └── svc
+│ └── servicecontext.go
+└── pb
+ └── hello
+ ├── hello.pb.go
+ └── hello_grpc.pb.go
+```
\ No newline at end of file
diff --git a/tools/goctl/rpc/cli/cli.go b/tools/goctl/rpc/cli/cli.go
index c6536991..d7c0fea5 100644
--- a/tools/goctl/rpc/cli/cli.go
+++ b/tools/goctl/rpc/cli/cli.go
@@ -42,6 +42,8 @@ var (
VarBoolIdea bool
// VarBoolVerbose describes whether verbose.
VarBoolVerbose bool
+ // VarBoolMultiple describes whether support generating multiple rpc services or not.
+ VarBoolMultiple bool
)
// RPCNew is to generate rpc greet service, this greet service can speed
diff --git a/tools/goctl/rpc/cli/zrpc.go b/tools/goctl/rpc/cli/zrpc.go
index 23ff2cd2..d79e2384 100644
--- a/tools/goctl/rpc/cli/zrpc.go
+++ b/tools/goctl/rpc/cli/zrpc.go
@@ -95,6 +95,7 @@ func ZRPC(_ *cobra.Command, args []string) error {
}
var ctx generator.ZRpcContext
+ ctx.Multiple = VarBoolMultiple
ctx.Src = source
ctx.GoOutput = goOut
ctx.GrpcOutput = grpcOut
diff --git a/tools/goctl/rpc/cmd.go b/tools/goctl/rpc/cmd.go
index be0c7de3..f948fa2f 100644
--- a/tools/goctl/rpc/cmd.go
+++ b/tools/goctl/rpc/cmd.go
@@ -37,25 +37,37 @@ var (
func init() {
Cmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file")
- Cmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
- Cmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
- Cmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
+ Cmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of "+
+ "the template, --home and --remote cannot be set at the same time, if they are, --remote has"+
+ " higher priority")
+ Cmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo"+
+ " of the template, --home and --remote cannot be set at the same time, if they are, --remote"+
+ " has higher priority\n\tThe git repo directory must be consistent with the "+
+ "https://github.com/zeromicro/go-zero-template directory structure")
+ Cmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the "+
+ "remote repo, it does work with --remote")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "")
newCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOpt, "go-grpc_opt", nil, "")
- newCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
- newCmd.Flags().BoolVar(&cli.VarBoolIdea, "idea", false, "Whether the command execution environment is from idea plugin.")
- newCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, "+
- "--home and --remote cannot be set at the same time, if they are, --remote has higher priority")
- newCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, "+
- "--home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo "+
- "directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
- newCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it "+
- "does work with --remote")
+ newCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file "+
+ "naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
+ newCmd.Flags().BoolVar(&cli.VarBoolIdea, "idea", false, "Whether the command "+
+ "execution environment is from idea plugin.")
+ newCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path "+
+ "of the template, --home and --remote cannot be set at the same time, if they are, --remote "+
+ "has higher priority")
+ newCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git "+
+ "repo of the template, --home and --remote cannot be set at the same time, if they are, "+
+ "--remote has higher priority\n\tThe git repo directory must be consistent with the "+
+ "https://github.com/zeromicro/go-zero-template directory structure")
+ newCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
+ "The branch of the remote repo, it does work with --remote")
newCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
newCmd.Flags().MarkHidden("go_opt")
newCmd.Flags().MarkHidden("go-grpc_opt")
+ protocCmd.Flags().BoolVarP(&cli.VarBoolMultiple, "multiple", "m", false,
+ "Generated in multiple rpc service mode")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOut, "go_out", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoGRPCOut, "go-grpc_out", nil, "")
protocCmd.Flags().StringSliceVar(&cli.VarStringSliceGoOpt, "go_opt", nil, "")
@@ -63,14 +75,17 @@ func init() {
protocCmd.Flags().StringSliceVar(&cli.VarStringSlicePlugin, "plugin", nil, "")
protocCmd.Flags().StringSliceVarP(&cli.VarStringSliceProtoPath, "proto_path", "I", nil, "")
protocCmd.Flags().StringVar(&cli.VarStringZRPCOut, "zrpc_out", "", "The zrpc output directory")
- protocCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
- protocCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, "+
- "--home and --remote cannot be set at the same time, if they are, --remote has higher priority")
- protocCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, "+
- "--home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo "+
- "directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
- protocCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it "+
- "does work with --remote")
+ protocCmd.Flags().StringVar(&cli.VarStringStyle, "style", "gozero", "The file "+
+ "naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]")
+ protocCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home "+
+ "path of the template, --home and --remote cannot be set at the same time, if they are, "+
+ "--remote has higher priority")
+ protocCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+
+ "git repo of the template, --home and --remote cannot be set at the same time, if they are, "+
+ "--remote has higher priority\n\tThe git repo directory must be consistent with the "+
+ "https://github.com/zeromicro/go-zero-template directory structure")
+ protocCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "",
+ "The branch of the remote repo, it does work with --remote")
protocCmd.Flags().BoolVarP(&cli.VarBoolVerbose, "verbose", "v", false, "Enable log output")
protocCmd.Flags().MarkHidden("go_out")
protocCmd.Flags().MarkHidden("go-grpc_out")
@@ -80,9 +95,15 @@ func init() {
protocCmd.Flags().MarkHidden("proto_path")
templateCmd.Flags().StringVar(&cli.VarStringOutput, "o", "", "Output a sample proto file")
- templateCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority")
- templateCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority\nThe git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure")
- templateCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch of the remote repo, it does work with --remote")
+ templateCmd.Flags().StringVar(&cli.VarStringHome, "home", "", "The goctl home"+
+ " path of the template, --home and --remote cannot be set at the same time, if they are, "+
+ "--remote has higher priority")
+ templateCmd.Flags().StringVar(&cli.VarStringRemote, "remote", "", "The remote "+
+ "git repo of the template, --home and --remote cannot be set at the same time, if they are, "+
+ "--remote has higher priority\n\tThe git repo directory must be consistent with the "+
+ "https://github.com/zeromicro/go-zero-template directory structure")
+ templateCmd.Flags().StringVar(&cli.VarStringBranch, "branch", "", "The branch"+
+ " of the remote repo, it does work with --remote")
Cmd.AddCommand(newCmd)
Cmd.AddCommand(protocCmd)
diff --git a/tools/goctl/rpc/generator/gen.go b/tools/goctl/rpc/generator/gen.go
index 636f126d..f72f9066 100644
--- a/tools/goctl/rpc/generator/gen.go
+++ b/tools/goctl/rpc/generator/gen.go
@@ -10,17 +10,27 @@ import (
)
type ZRpcContext struct {
- Src string
- ProtocCmd string
+ // Sre is the source file of the proto.
+ Src string
+ // ProtoCmd is the command to generate proto files.
+ ProtocCmd string
+ // ProtoGenGrpcDir is the directory to store the generated proto files.
ProtoGenGrpcDir string
- ProtoGenGoDir string
- IsGooglePlugin bool
- GoOutput string
- GrpcOutput string
- Output string
+ // ProtoGenGoDir is the directory to store the generated go files.
+ ProtoGenGoDir string
+ // IsGooglePlugin is the flag to indicate whether the proto file is generated by google plugin.
+ IsGooglePlugin bool
+ // GoOutput is the output directory of the generated go files.
+ GoOutput string
+ // GrpcOutput is the output directory of the generated grpc files.
+ GrpcOutput string
+ // Output is the output directory of the generated files.
+ Output string
+ // Multiple is the flag to indicate whether the proto file is generated in multiple mode.
+ Multiple bool
}
-// Generate generates an rpc service, through the proto file,
+// Generate generates a 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 *Generator) Generate(zctx *ZRpcContext) error {
@@ -45,7 +55,7 @@ func (g *Generator) Generate(zctx *ZRpcContext) error {
}
p := parser.NewDefaultProtoParser()
- proto, err := p.Parse(zctx.Src)
+ proto, err := p.Parse(zctx.Src, zctx.Multiple)
if err != nil {
return err
}
@@ -75,22 +85,22 @@ func (g *Generator) Generate(zctx *ZRpcContext) error {
return err
}
- err = g.GenLogic(dirCtx, proto, g.cfg)
+ err = g.GenLogic(dirCtx, proto, g.cfg, zctx)
if err != nil {
return err
}
- err = g.GenServer(dirCtx, proto, g.cfg)
+ err = g.GenServer(dirCtx, proto, g.cfg, zctx)
if err != nil {
return err
}
- err = g.GenMain(dirCtx, proto, g.cfg)
+ err = g.GenMain(dirCtx, proto, g.cfg, zctx)
if err != nil {
return err
}
- err = g.GenCall(dirCtx, proto, g.cfg)
+ err = g.GenCall(dirCtx, proto, g.cfg, zctx)
console.NewColorConsole().MarkDone()
diff --git a/tools/goctl/rpc/generator/gen_test.go b/tools/goctl/rpc/generator/gen_test.go
index e3b8a117..0919576c 100644
--- a/tools/goctl/rpc/generator/gen_test.go
+++ b/tools/goctl/rpc/generator/gen_test.go
@@ -12,7 +12,6 @@ import (
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stringx"
"github.com/zeromicro/go-zero/tools/goctl/rpc/execx"
- "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
)
func TestRpcGenerate(t *testing.T) {
@@ -41,8 +40,9 @@ func TestRpcGenerate(t *testing.T) {
// case go path
t.Run("GOPATH", func(t *testing.T) {
ctx := &ZRpcContext{
- Src: "./test.proto",
- ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir),
+ Src: "./test.proto",
+ ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s",
+ common, projectDir, projectDir),
IsGooglePlugin: true,
GoOutput: projectDir,
GrpcOutput: projectDir,
@@ -53,15 +53,16 @@ func TestRpcGenerate(t *testing.T) {
_, err = execx.Run("go test "+projectName, projectDir)
if err != nil {
assert.True(t, func() bool {
- return strings.Contains(err.Error(), "not in GOROOT") || strings.Contains(err.Error(), "cannot find package")
+ return strings.Contains(err.Error(),
+ "not in GOROOT") || strings.Contains(err.Error(), "cannot find package")
}())
}
})
// case go mod
t.Run("GOMOD", func(t *testing.T) {
- workDir := pathx.MustTempDir()
- name := filepath.Base(workDir)
+ workDir := projectDir
+ name := filepath.Base(projectDir)
_, err = execx.Run("go mod init "+name, workDir)
if err != nil {
logx.Error(err)
@@ -70,8 +71,9 @@ func TestRpcGenerate(t *testing.T) {
projectDir = filepath.Join(workDir, projectName)
ctx := &ZRpcContext{
- Src: "./test.proto",
- ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir),
+ Src: "./test.proto",
+ ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s",
+ common, projectDir, projectDir),
IsGooglePlugin: true,
GoOutput: projectDir,
GrpcOutput: projectDir,
@@ -79,31 +81,5 @@ func TestRpcGenerate(t *testing.T) {
}
err = g.Generate(ctx)
assert.Nil(t, err)
- _, err = execx.Run("go test "+projectName, projectDir)
- if err != nil {
- assert.True(t, func() bool {
- return strings.Contains(err.Error(), "not in GOROOT") || strings.Contains(err.Error(), "cannot find package")
- }())
- }
- })
-
- // case not in go mod and go path
- t.Run("OTHER", func(t *testing.T) {
- ctx := &ZRpcContext{
- Src: "./test.proto",
- ProtocCmd: fmt.Sprintf("protoc -I=%s test.proto --go_out=%s --go_opt=Mbase/common.proto=./base --go-grpc_out=%s", common, projectDir, projectDir),
- IsGooglePlugin: true,
- GoOutput: projectDir,
- GrpcOutput: projectDir,
- Output: projectDir,
- }
- err = g.Generate(ctx)
- assert.Nil(t, err)
- _, err = execx.Run("go test "+projectName, projectDir)
- if err != nil {
- assert.True(t, func() bool {
- return strings.Contains(err.Error(), "not in GOROOT") || strings.Contains(err.Error(), "cannot find package")
- }())
- }
})
}
diff --git a/tools/goctl/rpc/generator/gencall.go b/tools/goctl/rpc/generator/gencall.go
index 86706761..24331bd2 100644
--- a/tools/goctl/rpc/generator/gencall.go
+++ b/tools/goctl/rpc/generator/gencall.go
@@ -35,9 +35,88 @@ var callTemplateText string
// 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 *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config,
+ c *ZRpcContext) error {
+ if !c.Multiple {
+ return g.genCallInCompatibility(ctx, proto, cfg)
+ }
+
+ return g.genCallGroup(ctx, proto, cfg)
+}
+
+func (g *Generator) genCallGroup(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
dir := ctx.GetCall()
- service := proto.Service
+ head := util.GetHead(proto.Name)
+ for _, service := range proto.Service {
+ childPkg, err := dir.GetChildPackage(service.Name)
+ if err != nil {
+ return err
+ }
+
+ callFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name)
+ if err != nil {
+ return err
+ }
+
+ childDir := filepath.Base(childPkg)
+ filename := filepath.Join(dir.Filename, childDir, fmt.Sprintf("%s.go", callFilename))
+ isCallPkgSameToPbPkg := childDir == ctx.GetProtoGo().Filename
+ isCallPkgSameToGrpcPkg := childDir == ctx.GetProtoGo().Filename
+
+ functions, err := g.genFunction(proto.PbPackage, service, isCallPkgSameToGrpcPkg)
+ if err != nil {
+ return err
+ }
+
+ iFunctions, err := g.getInterfaceFuncs(proto.PbPackage, service, isCallPkgSameToGrpcPkg)
+ if err != nil {
+ return err
+ }
+
+ text, err := pathx.LoadTemplate(category, callTemplateFile, callTemplateText)
+ if err != nil {
+ return err
+ }
+
+ alias := collection.NewSet()
+ if !isCallPkgSameToPbPkg {
+ for _, item := range proto.Message {
+ msgName := getMessageName(*item.Message)
+ alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName),
+ fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
+ }
+ }
+
+ pbPackage := fmt.Sprintf(`"%s"`, ctx.GetPb().Package)
+ protoGoPackage := fmt.Sprintf(`"%s"`, ctx.GetProtoGo().Package)
+ if isCallPkgSameToGrpcPkg {
+ pbPackage = ""
+ protoGoPackage = ""
+ }
+
+ aliasKeys := alias.KeysStr()
+ sort.Strings(aliasKeys)
+ if err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
+ "name": callFilename,
+ "alias": strings.Join(aliasKeys, pathx.NL),
+ "head": head,
+ "filePackage": dir.Base,
+ "pbPackage": pbPackage,
+ "protoGoPackage": protoGoPackage,
+ "serviceName": stringx.From(service.Name).ToCamel(),
+ "functions": strings.Join(functions, pathx.NL),
+ "interface": strings.Join(iFunctions, pathx.NL),
+ }, filename, true); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (g *Generator) genCallInCompatibility(ctx DirContext, proto parser.Proto,
+ cfg *conf.Config) error {
+ dir := ctx.GetCall()
+ service := proto.Service[0]
head := util.GetHead(proto.Name)
isCallPkgSameToPbPkg := ctx.GetCall().Filename == ctx.GetPb().Filename
isCallPkgSameToGrpcPkg := ctx.GetCall().Filename == ctx.GetProtoGo().Filename
@@ -67,7 +146,8 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
if !isCallPkgSameToPbPkg {
for _, item := range proto.Message {
msgName := getMessageName(*item.Message)
- alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName), fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
+ alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName),
+ fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
}
}
@@ -79,7 +159,7 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
}
aliasKeys := alias.KeysStr()
sort.Strings(aliasKeys)
- err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
+ return util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
"name": callFilename,
"alias": strings.Join(aliasKeys, pathx.NL),
"head": head,
@@ -90,7 +170,6 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
"functions": strings.Join(functions, pathx.NL),
"interface": strings.Join(iFunctions, pathx.NL),
}, filename, true)
- return err
}
func getMessageName(msg proto.Message) string {
@@ -115,7 +194,8 @@ func getMessageName(msg proto.Message) string {
return strings.Join(list, "_")
}
-func (g *Generator) genFunction(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) {
+func (g *Generator) genFunction(goPackage string, service parser.Service,
+ isCallPkgSameToGrpcPkg bool) ([]string, error) {
functions := make([]string, 0)
for _, rpc := range service.RPC {
@@ -125,9 +205,11 @@ func (g *Generator) genFunction(goPackage string, service parser.Service, isCall
}
comment := parser.GetComment(rpc.Doc())
- streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
+ streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name),
+ parser.CamelCase(rpc.Name), "Client")
if isCallPkgSameToGrpcPkg {
- streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
+ streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name),
+ parser.CamelCase(rpc.Name), "Client")
}
buffer, err := util.With("sharedFn").Parse(text).Execute(map[string]interface{}{
"serviceName": stringx.From(service.Name).ToCamel(),
@@ -153,19 +235,23 @@ func (g *Generator) genFunction(goPackage string, service parser.Service, isCall
return functions, nil
}
-func (g *Generator) getInterfaceFuncs(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) {
+func (g *Generator) getInterfaceFuncs(goPackage string, service parser.Service,
+ isCallPkgSameToGrpcPkg bool) ([]string, error) {
functions := make([]string, 0)
for _, rpc := range service.RPC {
- text, err := pathx.LoadTemplate(category, callInterfaceFunctionTemplateFile, callInterfaceFunctionTemplate)
+ text, err := pathx.LoadTemplate(category, callInterfaceFunctionTemplateFile,
+ callInterfaceFunctionTemplate)
if err != nil {
return nil, err
}
comment := parser.GetComment(rpc.Doc())
- streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
+ streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name),
+ parser.CamelCase(rpc.Name), "Client")
if isCallPkgSameToGrpcPkg {
- streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
+ streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name),
+ parser.CamelCase(rpc.Name), "Client")
}
buffer, err := util.With("interfaceFn").Parse(text).Execute(
map[string]interface{}{
diff --git a/tools/goctl/rpc/generator/genlogic.go b/tools/goctl/rpc/generator/genlogic.go
index 9cbc9670..293779e7 100644
--- a/tools/goctl/rpc/generator/genlogic.go
+++ b/tools/goctl/rpc/generator/genlogic.go
@@ -27,17 +27,28 @@ func (l *{{.logicName}}) {{.method}} ({{if .hasReq}}in {{.request}}{{if .stream}
var logicTemplate string
// GenLogic generates the logic file of the rpc service, which corresponds to the RPC definition items in proto.
-func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Config,
+ c *ZRpcContext) error {
+ if !c.Multiple {
+ return g.genLogicInCompatibility(ctx, proto, cfg)
+ }
+
+ return g.genLogicGroup(ctx, proto, cfg)
+}
+
+func (g *Generator) genLogicInCompatibility(ctx DirContext, proto parser.Proto,
+ cfg *conf.Config) error {
dir := ctx.GetLogic()
- service := proto.Service.Service.Name
- for _, rpc := range proto.Service.RPC {
+ service := proto.Service[0].Service.Name
+ for _, rpc := range proto.Service[0].RPC {
+ logicName := fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel())
logicFilename, err := format.FileNamingFormat(cfg.NamingFormat, rpc.Name+"_logic")
if err != nil {
return err
}
filename := filepath.Join(dir.Filename, logicFilename+".go")
- functions, err := g.genLogicFunction(service, proto.PbPackage, rpc)
+ functions, err := g.genLogicFunction(service, proto.PbPackage, logicName, rpc)
if err != nil {
return err
}
@@ -50,9 +61,10 @@ func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Confi
return err
}
err = util.With("logic").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
- "logicName": fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel()),
- "functions": functions,
- "imports": strings.Join(imports.KeysStr(), pathx.NL),
+ "logicName": fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel()),
+ "functions": functions,
+ "packageName": "logic",
+ "imports": strings.Join(imports.KeysStr(), pathx.NL),
}, filename, false)
if err != nil {
return err
@@ -61,16 +73,72 @@ func (g *Generator) GenLogic(ctx DirContext, proto parser.Proto, cfg *conf.Confi
return nil
}
-func (g *Generator) genLogicFunction(serviceName, goPackage string, rpc *parser.RPC) (string, error) {
+func (g *Generator) genLogicGroup(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+ dir := ctx.GetLogic()
+ for _, item := range proto.Service {
+ serviceName := item.Name
+ for _, rpc := range item.RPC {
+ var (
+ err error
+ filename string
+ logicName string
+ logicFilename string
+ packageName string
+ )
+
+ logicName = fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel())
+ childPkg, err := dir.GetChildPackage(serviceName)
+ if err != nil {
+ return err
+ }
+
+ serviceDir := filepath.Base(childPkg)
+ nameJoin := fmt.Sprintf("%s_logic", serviceName)
+ packageName = strings.ToLower(stringx.From(nameJoin).ToCamel())
+ logicFilename, err = format.FileNamingFormat(cfg.NamingFormat, rpc.Name+"_logic")
+ if err != nil {
+ return err
+ }
+
+ filename = filepath.Join(dir.Filename, serviceDir, logicFilename+".go")
+ functions, err := g.genLogicFunction(serviceName, proto.PbPackage, logicName, rpc)
+ if err != nil {
+ return err
+ }
+
+ imports := collection.NewSet()
+ imports.AddStr(fmt.Sprintf(`"%v"`, ctx.GetSvc().Package))
+ imports.AddStr(fmt.Sprintf(`"%v"`, ctx.GetPb().Package))
+ text, err := pathx.LoadTemplate(category, logicTemplateFileFile, logicTemplate)
+ if err != nil {
+ return err
+ }
+
+ if err = util.With("logic").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
+ "logicName": logicName,
+ "functions": functions,
+ "packageName": packageName,
+ "imports": strings.Join(imports.KeysStr(), pathx.NL),
+ }, filename, false); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+func (g *Generator) genLogicFunction(serviceName, goPackage, logicName string,
+ rpc *parser.RPC) (string,
+ error) {
functions := make([]string, 0)
text, err := pathx.LoadTemplate(category, logicFuncTemplateFileFile, logicFunctionTemplate)
if err != nil {
return "", err
}
- logicName := stringx.From(rpc.Name + "_logic").ToCamel()
comment := parser.GetComment(rpc.Doc())
- streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(serviceName), parser.CamelCase(rpc.Name), "Server")
+ streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(serviceName),
+ parser.CamelCase(rpc.Name), "Server")
buffer, err := util.With("fun").Parse(text).Execute(map[string]interface{}{
"logicName": logicName,
"method": parser.CamelCase(rpc.Name),
diff --git a/tools/goctl/rpc/generator/genmain.go b/tools/goctl/rpc/generator/genmain.go
index c5ca2aff..8bbde495 100644
--- a/tools/goctl/rpc/generator/genmain.go
+++ b/tools/goctl/rpc/generator/genmain.go
@@ -11,14 +11,20 @@ import (
"github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
- "github.com/zeromicro/go-zero/tools/goctl/util/stringx"
)
//go:embed main.tpl
var mainTemplate string
+type MainServiceTemplateData struct {
+ Service string
+ ServerPkg string
+ Pkg string
+}
+
// GenMain generates the main file of the rpc service, which is an rpc service program call entry
-func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config,
+ c *ZRpcContext) error {
mainFilename, err := format.FileNamingFormat(cfg.NamingFormat, ctx.GetServiceName().Source())
if err != nil {
return err
@@ -28,9 +34,35 @@ func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config
imports := make([]string, 0)
pbImport := fmt.Sprintf(`"%v"`, ctx.GetPb().Package)
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
- remoteImport := fmt.Sprintf(`"%v"`, ctx.GetServer().Package)
configImport := fmt.Sprintf(`"%v"`, ctx.GetConfig().Package)
- imports = append(imports, configImport, pbImport, remoteImport, svcImport)
+ imports = append(imports, configImport, pbImport, svcImport)
+
+ var serviceNames []MainServiceTemplateData
+ for _, e := range proto.Service {
+ var (
+ remoteImport string
+ serverPkg string
+ )
+ if !c.Multiple {
+ serverPkg = "server"
+ remoteImport = fmt.Sprintf(`"%v"`, ctx.GetServer().Package)
+ } else {
+ childPkg, err := ctx.GetServer().GetChildPackage(e.Name)
+ if err != nil {
+ return err
+ }
+
+ serverPkg = filepath.Base(childPkg + "Server")
+ remoteImport = fmt.Sprintf(`%s "%v"`, serverPkg, childPkg)
+ }
+ imports = append(imports, remoteImport)
+ serviceNames = append(serviceNames, MainServiceTemplateData{
+ Service: parser.CamelCase(e.Name),
+ ServerPkg: serverPkg,
+ Pkg: proto.PbPackage,
+ })
+ }
+
text, err := pathx.LoadTemplate(category, mainTemplateFile, mainTemplate)
if err != nil {
return err
@@ -42,10 +74,9 @@ func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config
}
return util.With("main").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
- "serviceName": etcFileName,
- "imports": strings.Join(imports, pathx.NL),
- "pkg": proto.PbPackage,
- "serviceNew": stringx.From(proto.Service.Name).ToCamel(),
- "service": parser.CamelCase(proto.Service.Name),
+ "serviceName": etcFileName,
+ "imports": strings.Join(imports, pathx.NL),
+ "pkg": proto.PbPackage,
+ "serviceNames": serviceNames,
}, fileName, false)
}
diff --git a/tools/goctl/rpc/generator/genserver.go b/tools/goctl/rpc/generator/genserver.go
index 2a327ec5..675d78ce 100644
--- a/tools/goctl/rpc/generator/genserver.go
+++ b/tools/goctl/rpc/generator/genserver.go
@@ -18,7 +18,7 @@ import (
const functionTemplate = `
{{if .hasComment}}{{.comment}}{{end}}
func (s *{{.server}}Server) {{.method}} ({{if .notStream}}ctx context.Context,{{if .hasReq}} in {{.request}}{{end}}{{else}}{{if .hasReq}} in {{.request}},{{end}}stream {{.streamBody}}{{end}}) ({{if .notStream}}{{.response}},{{end}}error) {
- l := logic.New{{.logicName}}({{if .notStream}}ctx,{{else}}stream.Context(),{{end}}s.svcCtx)
+ l := {{.logicPkg}}.New{{.logicName}}({{if .notStream}}ctx,{{else}}stream.Context(),{{end}}s.svcCtx)
return l.{{.method}}({{if .hasReq}}in{{if .stream}} ,stream{{end}}{{else}}{{if .stream}}stream{{end}}{{end}})
}
`
@@ -27,7 +27,85 @@ func (s *{{.server}}Server) {{.method}} ({{if .notStream}}ctx context.Context,{{
var serverTemplate string
// GenServer generates rpc server file, which is an implementation of rpc server
-func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Config,
+ c *ZRpcContext) error {
+ if !c.Multiple {
+ return g.genServerInCompatibility(ctx, proto, cfg, c)
+ }
+
+ return g.genServerGroup(ctx, proto, cfg)
+}
+
+func (g *Generator) genServerGroup(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
+ dir := ctx.GetServer()
+ for _, service := range proto.Service {
+ var (
+ serverFile string
+ logicImport string
+ )
+
+ serverFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name+"_server")
+ if err != nil {
+ return err
+ }
+
+ serverChildPkg, err := dir.GetChildPackage(service.Name)
+ if err != nil {
+ return err
+ }
+
+ logicChildPkg, err := ctx.GetLogic().GetChildPackage(service.Name)
+ if err != nil {
+ return err
+ }
+
+ serverDir := filepath.Base(serverChildPkg)
+ logicImport = fmt.Sprintf(`"%v"`, logicChildPkg)
+ serverFile = filepath.Join(dir.Filename, serverDir, serverFilename+".go")
+
+ svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
+ pbImport := fmt.Sprintf(`"%v"`, ctx.GetPb().Package)
+
+ imports := collection.NewSet()
+ imports.AddStr(logicImport, svcImport, pbImport)
+
+ head := util.GetHead(proto.Name)
+
+ funcList, err := g.genFunctions(proto.PbPackage, service, true)
+ if err != nil {
+ return err
+ }
+
+ text, err := pathx.LoadTemplate(category, serverTemplateFile, serverTemplate)
+ if err != nil {
+ return err
+ }
+
+ notStream := false
+ for _, rpc := range service.RPC {
+ if !rpc.StreamsRequest && !rpc.StreamsReturns {
+ notStream = true
+ break
+ }
+ }
+
+ if err = util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
+ "head": head,
+ "unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
+ stringx.From(service.Name).ToCamel()),
+ "server": stringx.From(service.Name).ToCamel(),
+ "imports": strings.Join(imports.KeysStr(), pathx.NL),
+ "funcs": strings.Join(funcList, pathx.NL),
+ "notStream": notStream,
+ }, serverFile, true); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (g *Generator) genServerInCompatibility(ctx DirContext, proto parser.Proto,
+ cfg *conf.Config, c *ZRpcContext) error {
dir := ctx.GetServer()
logicImport := fmt.Sprintf(`"%v"`, ctx.GetLogic().Package)
svcImport := fmt.Sprintf(`"%v"`, ctx.GetSvc().Package)
@@ -37,14 +115,14 @@ func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Conf
imports.AddStr(logicImport, svcImport, pbImport)
head := util.GetHead(proto.Name)
- service := proto.Service
+ service := proto.Service[0]
serverFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name+"_server")
if err != nil {
return err
}
serverFile := filepath.Join(dir.Filename, serverFilename+".go")
- funcList, err := g.genFunctions(proto.PbPackage, service)
+ funcList, err := g.genFunctions(proto.PbPackage, service, false)
if err != nil {
return err
}
@@ -62,30 +140,44 @@ func (g *Generator) GenServer(ctx DirContext, proto parser.Proto, cfg *conf.Conf
}
}
- err = util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
- "head": head,
- "unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage, stringx.From(service.Name).ToCamel()),
- "server": stringx.From(service.Name).ToCamel(),
- "imports": strings.Join(imports.KeysStr(), pathx.NL),
- "funcs": strings.Join(funcList, pathx.NL),
- "notStream": notStream,
+ return util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
+ "head": head,
+ "unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
+ stringx.From(service.Name).ToCamel()),
+ "server": stringx.From(service.Name).ToCamel(),
+ "imports": strings.Join(imports.KeysStr(), pathx.NL),
+ "funcs": strings.Join(funcList, pathx.NL),
+ "notStream": notStream,
}, serverFile, true)
- return err
}
-func (g *Generator) genFunctions(goPackage string, service parser.Service) ([]string, error) {
- var functionList []string
+func (g *Generator) genFunctions(goPackage string, service parser.Service, multiple bool) ([]string, error) {
+ var (
+ functionList []string
+ logicPkg string
+ )
for _, rpc := range service.RPC {
text, err := pathx.LoadTemplate(category, serverFuncTemplateFile, functionTemplate)
if err != nil {
return nil, err
}
+ var logicName string
+ if !multiple {
+ logicPkg = "logic"
+ logicName = fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel())
+ } else {
+ nameJoin := fmt.Sprintf("%s_logic", service.Name)
+ logicPkg = strings.ToLower(stringx.From(nameJoin).ToCamel())
+ logicName = fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel())
+ }
+
comment := parser.GetComment(rpc.Doc())
- streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Server")
+ streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name),
+ parser.CamelCase(rpc.Name), "Server")
buffer, err := util.With("func").Parse(text).Execute(map[string]interface{}{
"server": stringx.From(service.Name).ToCamel(),
- "logicName": fmt.Sprintf("%sLogic", stringx.From(rpc.Name).ToCamel()),
+ "logicName": logicName,
"method": parser.CamelCase(rpc.Name),
"request": fmt.Sprintf("*%s.%s", goPackage, parser.CamelCase(rpc.RequestType)),
"response": fmt.Sprintf("*%s.%s", goPackage, parser.CamelCase(rpc.ReturnsType)),
@@ -95,6 +187,7 @@ func (g *Generator) genFunctions(goPackage string, service parser.Service) ([]st
"stream": rpc.StreamsRequest || rpc.StreamsReturns,
"notStream": !rpc.StreamsRequest && !rpc.StreamsReturns,
"streamBody": streamServer,
+ "logicPkg": logicPkg,
})
if err != nil {
return nil, err
diff --git a/tools/goctl/rpc/generator/logic.tpl b/tools/goctl/rpc/generator/logic.tpl
index b4ca2a1b..b8d81f0b 100644
--- a/tools/goctl/rpc/generator/logic.tpl
+++ b/tools/goctl/rpc/generator/logic.tpl
@@ -1,4 +1,4 @@
-package logic
+package {{.packageName}}
import (
"context"
diff --git a/tools/goctl/rpc/generator/main.tpl b/tools/goctl/rpc/generator/main.tpl
index 4e13a7c5..58cb6760 100644
--- a/tools/goctl/rpc/generator/main.tpl
+++ b/tools/goctl/rpc/generator/main.tpl
@@ -21,11 +21,10 @@ func main() {
var c config.Config
conf.MustLoad(*configFile, &c)
ctx := svc.NewServiceContext(c)
- svr := server.New{{.serviceNew}}Server(ctx)
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
- {{.pkg}}.Register{{.service}}Server(grpcServer, svr)
-
+{{range .serviceNames}} {{.Pkg}}.Register{{.Service}}Server(grpcServer, {{.ServerPkg}}.New{{.Service}}Server(ctx))
+{{end}}
if c.Mode == service.DevMode || c.Mode == service.TestMode {
reflection.Register(grpcServer)
}
diff --git a/tools/goctl/rpc/generator/mkdir.go b/tools/goctl/rpc/generator/mkdir.go
index 5f3d5814..2e8526fb 100644
--- a/tools/goctl/rpc/generator/mkdir.go
+++ b/tools/goctl/rpc/generator/mkdir.go
@@ -43,9 +43,10 @@ type (
// Dir defines a directory
Dir struct {
- Base string
- Filename string
- Package string
+ Base string
+ Filename string
+ Package string
+ GetChildPackage func(childPath string) (string, error)
}
defaultDirContext struct {
@@ -55,9 +56,11 @@ type (
}
)
-func mkdir(ctx *ctx.ProjectContext, proto parser.Proto, _ *conf.Config, c *ZRpcContext) (DirContext, error) {
+func mkdir(ctx *ctx.ProjectContext, proto parser.Proto, _ *conf.Config, c *ZRpcContext) (DirContext,
+ error) {
inner := make(map[string]Dir)
etcDir := filepath.Join(ctx.WorkDir, "etc")
+ clientDir := filepath.Join(ctx.WorkDir, "client")
internalDir := filepath.Join(ctx.WorkDir, "internal")
configDir := filepath.Join(internalDir, "config")
logicDir := filepath.Join(internalDir, "logic")
@@ -70,64 +73,125 @@ func mkdir(ctx *ctx.ProjectContext, proto parser.Proto, _ *conf.Config, c *ZRpcC
protoGoDir = c.ProtoGenGoDir
}
- callDir := filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name).ToCamel()))
- if strings.EqualFold(proto.Service.Name, filepath.Base(proto.GoPackage)) {
- callDir = filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name+"_client").ToCamel()))
+ getChildPackage := func(parent, childPath string) (string, error) {
+ child := strings.TrimPrefix(childPath, parent)
+ abs := filepath.Join(parent, strings.ToLower(child))
+ if c.Multiple {
+ if err := pathx.MkdirIfNotExist(abs); err != nil {
+ return "", err
+ }
+ }
+ childPath = strings.TrimPrefix(abs, ctx.Dir)
+ pkg := filepath.Join(ctx.Path, childPath)
+ return filepath.ToSlash(pkg), nil
+ }
+
+ if !c.Multiple {
+ callDir := filepath.Join(ctx.WorkDir,
+ strings.ToLower(stringx.From(proto.Service[0].Name).ToCamel()))
+ if strings.EqualFold(proto.Service[0].Name, filepath.Base(proto.GoPackage)) {
+ callDir = filepath.Join(ctx.WorkDir,
+ strings.ToLower(stringx.From(proto.Service[0].Name+"_client").ToCamel()))
+ }
+ inner[call] = Dir{
+ Filename: callDir,
+ Package: filepath.ToSlash(filepath.Join(ctx.Path,
+ strings.TrimPrefix(callDir, ctx.Dir))),
+ Base: filepath.Base(callDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(callDir, childPath)
+ },
+ }
+ } else {
+ inner[call] = Dir{
+ Filename: clientDir,
+ Package: filepath.ToSlash(filepath.Join(ctx.Path,
+ strings.TrimPrefix(clientDir, ctx.Dir))),
+ Base: filepath.Base(clientDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(clientDir, childPath)
+ },
+ }
}
inner[wd] = Dir{
Filename: ctx.WorkDir,
- Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(ctx.WorkDir, ctx.Dir))),
- Base: filepath.Base(ctx.WorkDir),
+ Package: filepath.ToSlash(filepath.Join(ctx.Path,
+ strings.TrimPrefix(ctx.WorkDir, ctx.Dir))),
+ Base: filepath.Base(ctx.WorkDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(ctx.WorkDir, childPath)
+ },
}
inner[etc] = Dir{
Filename: etcDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(etcDir, ctx.Dir))),
Base: filepath.Base(etcDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(etcDir, childPath)
+ },
}
inner[internal] = Dir{
Filename: internalDir,
- Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(internalDir, ctx.Dir))),
- Base: filepath.Base(internalDir),
+ Package: filepath.ToSlash(filepath.Join(ctx.Path,
+ strings.TrimPrefix(internalDir, ctx.Dir))),
+ Base: filepath.Base(internalDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(internalDir, childPath)
+ },
}
inner[config] = Dir{
Filename: configDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(configDir, ctx.Dir))),
Base: filepath.Base(configDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(configDir, childPath)
+ },
}
inner[logic] = Dir{
Filename: logicDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(logicDir, ctx.Dir))),
Base: filepath.Base(logicDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(logicDir, childPath)
+ },
}
inner[server] = Dir{
Filename: serverDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(serverDir, ctx.Dir))),
Base: filepath.Base(serverDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(serverDir, childPath)
+ },
}
inner[svc] = Dir{
Filename: svcDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(svcDir, ctx.Dir))),
Base: filepath.Base(svcDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(svcDir, childPath)
+ },
}
inner[pb] = Dir{
Filename: pbDir,
Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(pbDir, ctx.Dir))),
Base: filepath.Base(pbDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(pbDir, childPath)
+ },
}
inner[protoGo] = Dir{
Filename: protoGoDir,
- Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(protoGoDir, ctx.Dir))),
- Base: filepath.Base(protoGoDir),
+ Package: filepath.ToSlash(filepath.Join(ctx.Path,
+ strings.TrimPrefix(protoGoDir, ctx.Dir))),
+ Base: filepath.Base(protoGoDir),
+ GetChildPackage: func(childPath string) (string, error) {
+ return getChildPackage(protoGoDir, childPath)
+ },
}
- inner[call] = Dir{
- Filename: callDir,
- Package: filepath.ToSlash(filepath.Join(ctx.Path, strings.TrimPrefix(callDir, ctx.Dir))),
- Base: filepath.Base(callDir),
- }
for _, v := range inner {
err := pathx.MkdirIfNotExist(v.Filename)
if err != nil {
@@ -151,8 +215,9 @@ func (d *defaultDirContext) SetPbDir(pbDir, grpcDir string) {
d.inner[protoGo] = Dir{
Filename: grpcDir,
- Package: filepath.ToSlash(filepath.Join(d.ctx.Path, strings.TrimPrefix(grpcDir, d.ctx.Dir))),
- Base: filepath.Base(grpcDir),
+ Package: filepath.ToSlash(filepath.Join(d.ctx.Path,
+ strings.TrimPrefix(grpcDir, d.ctx.Dir))),
+ Base: filepath.Base(grpcDir),
}
}
diff --git a/tools/goctl/rpc/generator/template.go b/tools/goctl/rpc/generator/template.go
index 35fcc83c..0704dfec 100644
--- a/tools/goctl/rpc/generator/template.go
+++ b/tools/goctl/rpc/generator/template.go
@@ -23,18 +23,16 @@ const (
)
var templates = map[string]string{
- callTemplateFile: callTemplateText,
- callInterfaceFunctionTemplateFile: callInterfaceFunctionTemplate,
- callFunctionTemplateFile: callFunctionTemplate,
- configTemplateFileFile: configTemplate,
- etcTemplateFileFile: etcTemplate,
- logicTemplateFileFile: logicTemplate,
- logicFuncTemplateFileFile: logicFunctionTemplate,
- mainTemplateFile: mainTemplate,
- serverTemplateFile: serverTemplate,
- serverFuncTemplateFile: functionTemplate,
- svcTemplateFile: svcTemplate,
- rpcTemplateFile: rpcTemplateText,
+ callTemplateFile: callTemplateText,
+ configTemplateFileFile: configTemplate,
+ etcTemplateFileFile: etcTemplate,
+ logicTemplateFileFile: logicTemplate,
+ logicFuncTemplateFileFile: logicFunctionTemplate,
+ mainTemplateFile: mainTemplate,
+ serverTemplateFile: serverTemplate,
+ serverFuncTemplateFile: functionTemplate,
+ svcTemplateFile: svcTemplate,
+ rpcTemplateFile: rpcTemplateText,
}
// GenTemplates is the entry for command goctl template,
diff --git a/tools/goctl/rpc/parser/parser.go b/tools/goctl/rpc/parser/parser.go
index a6ff0610..1c80a4f2 100644
--- a/tools/goctl/rpc/parser/parser.go
+++ b/tools/goctl/rpc/parser/parser.go
@@ -1,8 +1,6 @@
package parser
import (
- "errors"
- "fmt"
"go/token"
"os"
"path/filepath"
@@ -14,7 +12,7 @@ import (
)
type (
- // DefaultProtoParser types a empty struct
+ // DefaultProtoParser types an empty struct
DefaultProtoParser struct{}
)
@@ -25,7 +23,7 @@ func NewDefaultProtoParser() *DefaultProtoParser {
// 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) {
+func (p *DefaultProtoParser) Parse(src string, multiple ...bool) (Proto, error) {
var ret Proto
abs, err := filepath.Abs(src)
@@ -45,7 +43,7 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
return ret, err
}
- var serviceList []Service
+ var serviceList Services
proto.Walk(
set,
proto.WithImport(func(i *proto.Import) {
@@ -76,31 +74,18 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
}
}),
)
- if len(serviceList) == 0 {
- return ret, errors.New("rpc service not found")
+ if err = serviceList.validate(abs, multiple...); err != nil {
+ return ret, err
}
- if len(serviceList) > 1 {
- return ret, errors.New("only one service expected")
- }
- service := serviceList[0]
- name := filepath.Base(abs)
-
- for _, rpc := range service.RPC {
- if strings.Contains(rpc.RequestType, ".") {
- return ret, fmt.Errorf("line %v:%v, request type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
- }
- if strings.Contains(rpc.ReturnsType, ".") {
- return ret, fmt.Errorf("line %v:%v, returns type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
- }
- }
if len(ret.GoPackage) == 0 {
ret.GoPackage = ret.Package.Name
}
+
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
ret.Src = abs
- ret.Name = name
- ret.Service = service
+ ret.Name = filepath.Base(abs)
+ ret.Service = serviceList
return ret, nil
}
diff --git a/tools/goctl/rpc/parser/parser_test.go b/tools/goctl/rpc/parser/parser_test.go
index b4fa19e0..4375b059 100644
--- a/tools/goctl/rpc/parser/parser_test.go
+++ b/tools/goctl/rpc/parser/parser_test.go
@@ -19,17 +19,22 @@ func TestDefaultProtoParse(t *testing.T) {
assert.Equal(t, "test", data.Package.Name)
assert.Equal(t, true, data.GoPackage == "go")
assert.Equal(t, true, data.PbPackage == "_go")
- assert.Equal(t, []string{"Inline", "Inner", "TestMessage", "TestReply", "TestReq"}, func() []string {
- var list []string
- for _, item := range data.Message {
- list = append(list, item.Name)
- }
- sort.Strings(list)
- return list
- }())
+ assert.Equal(t, []string{"Inline", "Inner", "TestMessage", "TestReply", "TestReq"},
+ func() []string {
+ var list []string
+ for _, item := range data.Message {
+ list = append(list, item.Name)
+ }
+ sort.Strings(list)
+ return list
+ }())
assert.Equal(t, true, func() bool {
- s := data.Service
+ if len(data.Service) != 1 {
+ return false
+ }
+
+ s := data.Service[0]
if s.Name != "TestService" {
return false
}
diff --git a/tools/goctl/rpc/parser/proto.go b/tools/goctl/rpc/parser/proto.go
index 084f824d..a08137bf 100644
--- a/tools/goctl/rpc/parser/proto.go
+++ b/tools/goctl/rpc/parser/proto.go
@@ -9,5 +9,5 @@ type Proto struct {
GoPackage string
Import []Import
Message []Message
- Service Service
+ Service Services
}
diff --git a/tools/goctl/rpc/parser/service.go b/tools/goctl/rpc/parser/service.go
index 3c7dc2bd..b060e2fd 100644
--- a/tools/goctl/rpc/parser/service.go
+++ b/tools/goctl/rpc/parser/service.go
@@ -1,10 +1,54 @@
package parser
-import "github.com/emicklei/proto"
+import (
+ "errors"
+ "fmt"
+ "path/filepath"
+ "strings"
-// Service describes the rpc service, which is the relevant
-// content after the translation of the proto file
-type Service struct {
- *proto.Service
- RPC []*RPC
+ "github.com/emicklei/proto"
+)
+
+type (
+ // Services is a slice of Service.
+ Services []Service
+
+ // Service describes the rpc service, which is the relevant
+ // content after the translation of the proto file
+ Service struct {
+ *proto.Service
+ RPC []*RPC
+ }
+)
+
+func (s Services) validate(filename string, multipleOpt ...bool) error {
+ if len(s) == 0 {
+ return errors.New("rpc service not found")
+ }
+
+ var multiple bool
+ for _, c := range multipleOpt {
+ multiple = c
+ }
+
+ if !multiple && len(s) > 1 {
+ return errors.New("only one service expected")
+ }
+
+ name := filepath.Base(filename)
+ for _, service := range s {
+ for _, rpc := range service.RPC {
+ if strings.Contains(rpc.RequestType, ".") {
+ return fmt.Errorf("line %v:%v, request type must defined in %s",
+ rpc.Position.Line,
+ rpc.Position.Column, name)
+ }
+ if strings.Contains(rpc.ReturnsType, ".") {
+ return fmt.Errorf("line %v:%v, returns type must defined in %s",
+ rpc.Position.Line,
+ rpc.Position.Column, name)
+ }
+ }
+ }
+ return nil
}