feat: Support for multiple rpc service generation and rpc grouping (#1972)

* Add group & compatible flag

* Add group & compatible flag

* Support for multiple rpc service generation and rpc grouping

* Support for multiple rpc service generation and rpc grouping

* Format code

* Format code

* Add comments

* Fix unit test

* Refactor function name

* Add example & Update grpc readme

* go mod tidy

* update mod

* update mod
This commit is contained in:
anqiansong 2022-07-21 12:47:46 +08:00 committed by GitHub
parent 1b51d0ce82
commit ca3c687f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 2305 additions and 377 deletions

2
go.mod
View File

@ -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
)

View File

@ -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);
}

View File

@ -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...)
}

View File

@ -0,0 +1,6 @@
Name: hello.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: hello.rpc

View File

@ -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()
}

View File

@ -0,0 +1,7 @@
package config
import "github.com/zeromicro/go-zero/zrpc"
type Config struct {
zrpc.RpcServerConf
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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",
}

View File

@ -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);
}

View File

@ -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...)
}

View File

@ -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...)
}

View File

@ -0,0 +1,6 @@
Name: hi.rpc
ListenOn: 127.0.0.1:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: hi.rpc

View File

@ -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()
}

View File

@ -0,0 +1,7 @@
package config
import "github.com/zeromicro/go-zero/zrpc"
type Config struct {
zrpc.RpcServerConf
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -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",
}

View File

@ -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 ./...

View File

@ -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 ./...

View File

@ -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
)

View File

@ -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=

View File

@ -7,7 +7,7 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块支持prot
* 简单易用
* 快速提升开发效率
* 出错率低
* 贴近protoc
* 贴近 protoc
## 快速开始
@ -24,168 +24,41 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块支持prot
执行后代码结构如下:
```golang
```text
.
├── etc // yaml配置文件
│ └── greet.yaml
├── go.mod
├── greet // pb.go文件夹①
│ └── greet.pb.go
├── greet.go // main函数
├── greet.proto // proto 文件
├── greetclient // call logic ②
│ └── greet.go
└── internal
├── config // yaml配置对应的实体
│ └── config.go
├── logic // 业务代码
│ └── pinglogic.go
├── server // rpc server
│ └── greetserver.go
└── svc // 依赖资源
└── servicecontext.go
```
> ① pb文件夹名老版本文件夹固定为pb称取自于proto文件中option go_package的值最后一层级按照一定格式进行转换若无此声明则取自于package的值大致代码如下
```go
if option.Name == "go_package" {
ret.GoPackage = option.Constant.Source
}
...
if len(ret.GoPackage) == 0 {
ret.GoPackage = ret.Package.Name
}
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
...
└── greet
├── etc
│   └── greet.yaml
├── greet
│   ├── greet.go
│   ├── greet.pb.go
│   └── greet_grpc.pb.go
├── greet.go
├── greet.proto
└── internal
├── config
│   └── config.go
├── logic
│   └── pinglogic.go
├── server
│   └── greetserver.go
└── svc
└── servicecontext.go
```
> GoSanitized方法请参考google.golang.org/protobuf@v1.25.0/internal/strs/strings.go:71
> ② call 层文件夹名称取自于proto中service的名称如该sercice的名称和pb文件夹名称相等则会在srervice后面补充client进行区分使pb和call分隔。
```go
if strings.ToLower(proto.Service.Name) == strings.ToLower(proto.GoPackage) {
callDir = filepath.Join(ctx.WorkDir, strings.ToLower(stringx.From(proto.Service.Name+"_client").ToCamel()))
}
```
rpc一键生成常见问题解决<a href="#常见问题解决">常见问题解决</a>
### 方式二通过指定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并且已经设置环境变量
* 更多问题请见 <a href="#注意事项">注意事项</a>
## 用法
### rpc服务生成用法
```Bash
goctl rpc proto -h
$ goctl rpc template -o=user.proto
```
```Bash
NAME:
goctl rpc proto - generate rpc from proto
USAGE:
goctl rpc proto [command options] [arguments...]
OPTIONS:
--src value, -s value the file path of the proto source file
--proto_path value, -I value native command of protoc, specify the directory in which to search for imports. [optional]
--go_opt value native command of protoc-gen-go, specify the mapping from proto to go, eg --go_opt=proto_import=go_package_import. [optional]
--dir value, -d value the target path of the code
--style value the file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md]
--idea whether the command execution environment is from idea plugin. [optional]
```
### 参数说明
* --src 必填proto数据源目前暂时支持单个proto文件生成
* --proto_path 可选protoc原生子命令用于指定proto import从何处查找可指定多个路径,如`goctl rpc -I={path1} -I={path2} ...`
,在没有import时可不填。当前proto路径不用指定已经内置`-I`的详细用法请参考`protoc -h`
* --go_opt 可选protoc-gen-go插件原生flag用于指定go_package
* --dir 可选默认为proto文件所在目录生成代码的目标目录
* --style 可选,指定生成文件名的命名风格
* --idea 可选是否为idea插件中执行终端执行可以忽略
### 开发人员需要做什么
关注业务代码编写将重复性、与业务无关的工作交给goctl生成好rpc服务代码后开发人员仅需要修改
* 服务中的配置文件编写(etc/xx.json、internal/config/config.go)
* 服务中业务逻辑编写(internal/logic/xxlogic.go)
* 服务中资源上下文的编写(internal/svc/servicecontext.go)
### 注意事项
* proto不支持暂多文件同时生成
* proto不支持外部依赖包引入message不支持inline
* 目前main文件、shared文件、handler文件会被强制覆盖而和开发人员手动需要编写的则不会覆盖生成这一类在代码头部均有
```shell script
// Code generated by goctl. DO NOT EDIT!
// Source: xxx.proto
```
的标识,请注意不要将也写业务性代码写在里面。
## proto import
* 对于rpc中的requestType和returnType必须在main proto文件定义对于proto中的message可以像protoc一样import其他proto文件。
proto示例:
### 错误import
```proto
syntax = "proto3";
package greet;
import "base/common.proto"
package user;
option go_package="./user";
message Request {
string ping = 1;
@ -195,40 +68,136 @@ message Response {
string pong = 1;
}
service Greet {
rpc Ping(base.In) returns(base.Out);// request和return 不支持import
}
```
### 正确import
```proto
syntax = "proto3";
package greet;
import "base/common.proto"
message Request {
base.In in = 1;// 支持import
}
message Response {
base.Out out = 2;// 支持import
}
service Greet {
service User {
rpc Ping(Request) returns(Response);
}
```
## 常见问题解决(go mod工程)
* 生成rpc服务代码
* 错误一:
```text
A required privilege is not held by the client.
```bash
$ goctl rpc protoc user.proto --go_out=. --go-grpc_out=. --zrpc_out=.
```
这个问题只有goctl 版本在`goctl.exe version 1.2.1` 以后的 Windows操作系统出现主要原因是goctl需要以管理员身份运行这样才能将`goctl.exe` 创建一个 `ptocot-gen-gcotl`
的符号链接。
## 用法
### rpc 服务生成用法
```Bash
$ goctl rpc protoc -h
Generate grpc code
Usage:
goctl rpc protoc [flags]
Examples:
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
Flags:
--branch string The branch of the remote repo, it does work with --remote
-h, --help help for protoc
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
-m, --multiple Generated in multiple rpc service mode
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
-v, --verbose Enable log output
--zrpc_out string The zrpc output directory
```
### 参数说明
* --branch 指定远程仓库模板分支
* --home 指定goctl模板根目录
* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service且多个 rpc service 会分组。
* --style 指定文件输出格式
* -v, --verbose 显示日志
* --zrpc_out 指定zrpc输出目录
> ## --multiple
> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
> 1. 支持 1 到多个 rpc service
> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service
> 3. rpc client 的文件目录变更为固定名称 `client`
>
> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
> 1. 有且只能有一个 rpc service
## rpc 服务生成 example
详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)
## --multiple 为 true 和 false 的目录区别
源 proto 文件
```protobuf
syntax = "proto3";
package hello;
option go_package = "./hello";
message HelloReq {
string in = 1;
}
message HelloResp {
string msg = 1;
}
service Greet {
rpc SayHello(HelloReq) returns (HelloResp);
}
```
### --multiple=true
```text
hello
├── client // 区别1rpc client 目录固定为 client 名称
│   └── greet // 区别2会按照 rpc service 名称分组
│   └── greet.go
├── etc
│   └── hello.yaml
├── hello.go
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   └── greet // 区别2会按照 rpc service 名称分组
│   │   └── sayhellologic.go
│   ├── server
│   │   └── greet // 区别2会按照 rpc service 名称分组
│   │   └── greetserver.go
│   └── svc
│   └── servicecontext.go
└── pb
└── hello
├── hello.pb.go
└── hello_grpc.pb.go
```
### --multiple=false (旧版本目录,向后兼容)
```text
hello
├── etc
│   └── hello.yaml
├── greet
│   └── greet.go
├── hello.go
├── internal
│   ├── config
│   │   └── config.go
│   ├── logic
│   │   └── sayhellologic.go
│   ├── server
│   │   └── greetserver.go
│   └── svc
│   └── servicecontext.go
└── pb
└── hello
├── hello.pb.go
└── hello_grpc.pb.go
```

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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")
}())
}
})
}

View File

@ -35,9 +35,88 @@ var callTemplateText string
// GenCall generates the rpc client code, which is the entry point for the rpc service call.
// It is a layer of encapsulation for the rpc client and shields the details in the pb.
func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config,
c *ZRpcContext) error {
if !c.Multiple {
return g.genCallInCompatibility(ctx, proto, cfg)
}
return g.genCallGroup(ctx, proto, cfg)
}
func (g *Generator) genCallGroup(ctx DirContext, proto parser.Proto, cfg *conf.Config) error {
dir := ctx.GetCall()
service := proto.Service
head := util.GetHead(proto.Name)
for _, service := range proto.Service {
childPkg, err := dir.GetChildPackage(service.Name)
if err != nil {
return err
}
callFilename, err := format.FileNamingFormat(cfg.NamingFormat, service.Name)
if err != nil {
return err
}
childDir := filepath.Base(childPkg)
filename := filepath.Join(dir.Filename, childDir, fmt.Sprintf("%s.go", callFilename))
isCallPkgSameToPbPkg := childDir == ctx.GetProtoGo().Filename
isCallPkgSameToGrpcPkg := childDir == ctx.GetProtoGo().Filename
functions, err := g.genFunction(proto.PbPackage, service, isCallPkgSameToGrpcPkg)
if err != nil {
return err
}
iFunctions, err := g.getInterfaceFuncs(proto.PbPackage, service, isCallPkgSameToGrpcPkg)
if err != nil {
return err
}
text, err := pathx.LoadTemplate(category, callTemplateFile, callTemplateText)
if err != nil {
return err
}
alias := collection.NewSet()
if !isCallPkgSameToPbPkg {
for _, item := range proto.Message {
msgName := getMessageName(*item.Message)
alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName),
fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
}
}
pbPackage := fmt.Sprintf(`"%s"`, ctx.GetPb().Package)
protoGoPackage := fmt.Sprintf(`"%s"`, ctx.GetProtoGo().Package)
if isCallPkgSameToGrpcPkg {
pbPackage = ""
protoGoPackage = ""
}
aliasKeys := alias.KeysStr()
sort.Strings(aliasKeys)
if err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
"name": callFilename,
"alias": strings.Join(aliasKeys, pathx.NL),
"head": head,
"filePackage": dir.Base,
"pbPackage": pbPackage,
"protoGoPackage": protoGoPackage,
"serviceName": stringx.From(service.Name).ToCamel(),
"functions": strings.Join(functions, pathx.NL),
"interface": strings.Join(iFunctions, pathx.NL),
}, filename, true); err != nil {
return err
}
}
return nil
}
func (g *Generator) genCallInCompatibility(ctx DirContext, proto parser.Proto,
cfg *conf.Config) error {
dir := ctx.GetCall()
service := proto.Service[0]
head := util.GetHead(proto.Name)
isCallPkgSameToPbPkg := ctx.GetCall().Filename == ctx.GetPb().Filename
isCallPkgSameToGrpcPkg := ctx.GetCall().Filename == ctx.GetProtoGo().Filename
@ -67,7 +146,8 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
if !isCallPkgSameToPbPkg {
for _, item := range proto.Message {
msgName := getMessageName(*item.Message)
alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName), fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
alias.AddStr(fmt.Sprintf("%s = %s", parser.CamelCase(msgName),
fmt.Sprintf("%s.%s", proto.PbPackage, parser.CamelCase(msgName))))
}
}
@ -79,7 +159,7 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
}
aliasKeys := alias.KeysStr()
sort.Strings(aliasKeys)
err = util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
return util.With("shared").GoFmt(true).Parse(text).SaveTo(map[string]interface{}{
"name": callFilename,
"alias": strings.Join(aliasKeys, pathx.NL),
"head": head,
@ -90,7 +170,6 @@ func (g *Generator) GenCall(ctx DirContext, proto parser.Proto, cfg *conf.Config
"functions": strings.Join(functions, pathx.NL),
"interface": strings.Join(iFunctions, pathx.NL),
}, filename, true)
return err
}
func getMessageName(msg proto.Message) string {
@ -115,7 +194,8 @@ func getMessageName(msg proto.Message) string {
return strings.Join(list, "_")
}
func (g *Generator) genFunction(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) {
func (g *Generator) genFunction(goPackage string, service parser.Service,
isCallPkgSameToGrpcPkg bool) ([]string, error) {
functions := make([]string, 0)
for _, rpc := range service.RPC {
@ -125,9 +205,11 @@ func (g *Generator) genFunction(goPackage string, service parser.Service, isCall
}
comment := parser.GetComment(rpc.Doc())
streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name),
parser.CamelCase(rpc.Name), "Client")
if isCallPkgSameToGrpcPkg {
streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name),
parser.CamelCase(rpc.Name), "Client")
}
buffer, err := util.With("sharedFn").Parse(text).Execute(map[string]interface{}{
"serviceName": stringx.From(service.Name).ToCamel(),
@ -153,19 +235,23 @@ func (g *Generator) genFunction(goPackage string, service parser.Service, isCall
return functions, nil
}
func (g *Generator) getInterfaceFuncs(goPackage string, service parser.Service, isCallPkgSameToGrpcPkg bool) ([]string, error) {
func (g *Generator) getInterfaceFuncs(goPackage string, service parser.Service,
isCallPkgSameToGrpcPkg bool) ([]string, error) {
functions := make([]string, 0)
for _, rpc := range service.RPC {
text, err := pathx.LoadTemplate(category, callInterfaceFunctionTemplateFile, callInterfaceFunctionTemplate)
text, err := pathx.LoadTemplate(category, callInterfaceFunctionTemplateFile,
callInterfaceFunctionTemplate)
if err != nil {
return nil, err
}
comment := parser.GetComment(rpc.Doc())
streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
streamServer := fmt.Sprintf("%s.%s_%s%s", goPackage, parser.CamelCase(service.Name),
parser.CamelCase(rpc.Name), "Client")
if isCallPkgSameToGrpcPkg {
streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name), parser.CamelCase(rpc.Name), "Client")
streamServer = fmt.Sprintf("%s_%s%s", parser.CamelCase(service.Name),
parser.CamelCase(rpc.Name), "Client")
}
buffer, err := util.With("interfaceFn").Parse(text).Execute(
map[string]interface{}{

View File

@ -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),

View File

@ -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)
}

View File

@ -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

View File

@ -1,4 +1,4 @@
package logic
package {{.packageName}}
import (
"context"

View File

@ -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)
}

View File

@ -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),
}
}

View File

@ -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,

View File

@ -1,8 +1,6 @@
package parser
import (
"errors"
"fmt"
"go/token"
"os"
"path/filepath"
@ -14,7 +12,7 @@ import (
)
type (
// DefaultProtoParser types a empty struct
// DefaultProtoParser types an empty struct
DefaultProtoParser struct{}
)
@ -25,7 +23,7 @@ func NewDefaultProtoParser() *DefaultProtoParser {
// Parse provides to parse the proto file into a golang structure,
// which is convenient for subsequent rpc generation and use
func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
func (p *DefaultProtoParser) Parse(src string, multiple ...bool) (Proto, error) {
var ret Proto
abs, err := filepath.Abs(src)
@ -45,7 +43,7 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
return ret, err
}
var serviceList []Service
var serviceList Services
proto.Walk(
set,
proto.WithImport(func(i *proto.Import) {
@ -76,31 +74,18 @@ func (p *DefaultProtoParser) Parse(src string) (Proto, error) {
}
}),
)
if len(serviceList) == 0 {
return ret, errors.New("rpc service not found")
if err = serviceList.validate(abs, multiple...); err != nil {
return ret, err
}
if len(serviceList) > 1 {
return ret, errors.New("only one service expected")
}
service := serviceList[0]
name := filepath.Base(abs)
for _, rpc := range service.RPC {
if strings.Contains(rpc.RequestType, ".") {
return ret, fmt.Errorf("line %v:%v, request type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
}
if strings.Contains(rpc.ReturnsType, ".") {
return ret, fmt.Errorf("line %v:%v, returns type must defined in %s", rpc.Position.Line, rpc.Position.Column, name)
}
}
if len(ret.GoPackage) == 0 {
ret.GoPackage = ret.Package.Name
}
ret.PbPackage = GoSanitized(filepath.Base(ret.GoPackage))
ret.Src = abs
ret.Name = name
ret.Service = service
ret.Name = filepath.Base(abs)
ret.Service = serviceList
return ret, nil
}

View File

@ -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
}

View File

@ -9,5 +9,5 @@ type Proto struct {
GoPackage string
Import []Import
Message []Message
Service Service
Service Services
}

View File

@ -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
}