diff --git a/go.mod b/go.mod index 090d3f93f399..c76614b02a55 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 000000000000..0ea428d0e863 --- /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 000000000000..ec9d3c18c592 --- /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 000000000000..91d30bb5c487 --- /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 000000000000..dd92f6370268 --- /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 000000000000..c1f85b99ac9f --- /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 000000000000..c94994e44e56 --- /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 000000000000..f0a4d383aecf --- /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 000000000000..961a318deb4d --- /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 000000000000..3d9e24bdcd6d --- /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 000000000000..1eb025b2f837 --- /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 000000000000..c75f577cb89c --- /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 000000000000..7a346baa9293 --- /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 000000000000..3c0b15b67737 --- /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 000000000000..ad1c83750d67 --- /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 000000000000..9e6cc0d0ef5d --- /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 000000000000..c1f85b99ac9f --- /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 000000000000..697ade527005 --- /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 000000000000..51dec93a505d --- /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 000000000000..80c08fcb05eb --- /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 000000000000..ac89b0c633d8 --- /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 000000000000..4308e1fa848f --- /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 000000000000..fe4af36e8a86 --- /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 000000000000..d523fb1a850a --- /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 000000000000..62c203268589 --- /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 000000000000..a0cdf99c61a1 --- /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 000000000000..4c4717de800c --- /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 8d822916a759..01907f88d07f 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 32089ba092dd..afb9f8233108 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 8a006ff59f3a..2394fbd1bb8b 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,211 +24,180 @@ 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 ``` + +```proto +syntax = "proto3"; -```Bash -NAME: - goctl rpc proto - generate rpc from proto +package user; +option go_package="./user"; -USAGE: - goctl rpc proto [command options] [arguments...] +message Request { + string ping = 1; +} -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] +message Response { + string pong = 1; +} +service User { + rpc Ping(Request) returns(Response); +} ``` + -### 参数说明 - -* --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文件会被强制覆盖,而和开发人员手动需要编写的则不会覆盖生成,这一类在代码头部均有 +* 生成rpc服务代码 -```shell script - // Code generated by goctl. DO NOT EDIT! - // Source: xxx.proto +```bash +$ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=. ``` -的标识,请注意不要将也写业务性代码写在里面。 - -## proto import -* 对于rpc中的requestType和returnType必须在main proto文件定义,对于proto中的message可以像protoc一样import其他proto文件。 -proto示例: +## 用法 -### 错误import -```proto -syntax = "proto3"; +### rpc 服务生成用法 -package greet; +```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 +``` -import "base/common.proto" +### 参数说明 -message Request { - string ping = 1; -} +* --branch 指定远程仓库模板分支 +* --home 指定goctl模板根目录 +* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。 +* --style 指定文件输出格式 +* -v, --verbose 显示日志 +* --zrpc_out 指定zrpc输出目录 -message Response { - string pong = 1; -} +> ## --multiple +> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性 +> 1. 支持 1 到多个 rpc service +> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service) +> 3. rpc client 的文件目录变更为固定名称 `client` +> +> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容) +> 1. 有且只能有一个 rpc service -service Greet { - rpc Ping(base.In) returns(base.Out);// request和return 不支持import -} -``` +## rpc 服务生成 example +详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example) +## --multiple 为 true 和 false 的目录区别 +源 proto 文件 -### 正确import -```proto +```protobuf syntax = "proto3"; -package greet; +package hello; -import "base/common.proto" +option go_package = "./hello"; -message Request { - base.In in = 1;// 支持import +message HelloReq { + string in = 1; } -message Response { - base.Out out = 2;// 支持import +message HelloResp { + string msg = 1; } service Greet { - rpc Ping(Request) returns(Response); + rpc SayHello(HelloReq) returns (HelloResp); } ``` -## 常见问题解决(go mod工程) +### --multiple=true -* 错误一: ```text -A required privilege is not held by the client. +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 ``` -这个问题只有goctl 版本在`goctl.exe version 1.2.1` 以后的 Windows操作系统出现,主要原因是goctl需要以管理员身份运行,这样才能将`goctl.exe` 创建一个 `ptocot-gen-gcotl` -的符号链接。 +### --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 c65369916c19..d7c0fea53677 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 23ff2cd24f1e..d79e2384f22c 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 be0c7de3c3cd..f948fa2f1001 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 636f126d800c..f72f9066ca8b 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 e3b8a117ef1c..0919576cbbcb 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 86706761ddd2..24331bd25ecf 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() + 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 + 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 9cbc96705c20..293779e74b26 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 c5ca2affe702..8bbde4958b9e 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 2a327ec57567..675d78ce6533 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 b4ca2a1b9e23..b8d81f0b6f53 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 4e13a7c5f8a1..58cb676062f5 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 5f3d5814ed61..2e8526fbc1d1 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 35fcc83c5bb1..0704dfec6fc1 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 a6ff061027da..1c80a4f299ba 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 len(serviceList) > 1 { - return ret, errors.New("only one service expected") + if err = serviceList.validate(abs, multiple...); err != nil { + return ret, err } - 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 b4fa19e0c9de..4375b0599530 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 084f824d2223..a08137bffd1d 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 3c7dc2bdde04..b060e2fd341f 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 }