diff --git a/.github/workflows/gf.yml b/.github/workflows/gf.yml index 32d743cd4..a85a987a2 100644 --- a/.github/workflows/gf.yml +++ b/.github/workflows/gf.yml @@ -111,6 +111,7 @@ jobs: - 9001:9001 # Polaris backend server. + # docker run -d --name polaris -p 8090:8090 -p 8091:8091 -p 8093:8093 loads/polaris-server-standalone:1.11.2 polaris: image: loads/polaris-server-standalone:1.11.2 ports: diff --git a/cmd/gf/internal/cmd/cmd_gen_pbentity.go b/cmd/gf/internal/cmd/cmd_gen_pbentity.go index 7b013736d..545963512 100644 --- a/cmd/gf/internal/cmd/cmd_gen_pbentity.go +++ b/cmd/gf/internal/cmd/cmd_gen_pbentity.go @@ -1,8 +1,6 @@ package cmd -import ( - "github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpbentity" -) +import "github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpbentity" type ( cGenPbEntity = genpbentity.CGenPbEntity diff --git a/cmd/gf/internal/cmd/gendao/gendao.go b/cmd/gf/internal/cmd/gendao/gendao.go index 4d1dfaf2c..e600d0772 100644 --- a/cmd/gf/internal/cmd/gendao/gendao.go +++ b/cmd/gf/internal/cmd/gendao/gendao.go @@ -216,6 +216,7 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) { } removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",") if in.ImportPrefix == "" { + mlog.Debug(`import prefix is empty, trying calculating the import package path using go.mod`) if !gfile.Exists("go.mod") { mlog.Fatal("go.mod does not exist in current working directory") } diff --git a/cmd/gf/internal/cmd/genpb/genpb.go b/cmd/gf/internal/cmd/genpb/genpb.go index 0c2724dd7..0806d9bb0 100644 --- a/cmd/gf/internal/cmd/genpb/genpb.go +++ b/cmd/gf/internal/cmd/genpb/genpb.go @@ -7,39 +7,76 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gproc" + "github.com/gogf/gf/v2/util/gtag" ) type ( CGenPb struct{} CGenPbInput struct { - g.Meta `name:"pb" brief:"parse proto files and generate protobuf go files"` - Path string `name:"path" short:"p" dc:"protobuf file folder path" d:"manifest/protobuf"` - OutputApi string `name:"outputApi" short:"oa" dc:"output folder path storing generated go files of api" d:"api"` - OutputCtrl string `name:"outputCtrl" short:"oc" dc:"output folder path storing generated go files of controller" d:"internal/controller"` + g.Meta `name:"pb" config:"{CGenPbConfig}" brief:"{CGenPbBrief}" eg:"{CGenPbEg}"` + Path string `name:"path" short:"p" dc:"protobuf file folder path" d:"manifest/protobuf"` + OutputApi string `name:"api" short:"a" dc:"output folder path storing generated go files of api" d:"api"` + OutputCtrl string `name:"ctrl" short:"c" dc:"output folder path storing generated go files of controller" d:"internal/controller"` } CGenPbOutput struct{} ) +const ( + CGenPbConfig = `gfcli.gen.pb` + CGenPbBrief = `parse proto files and generate protobuf go files` + CGenPbEg = ` +gf gen pb +gf gen pb -p . -a . -p . +` +) + +func init() { + gtag.Sets(g.MapStrStr{ + `CGenPbEg`: CGenPbEg, + `CGenPbBrief`: CGenPbBrief, + `CGenPbConfig`: CGenPbConfig, + }) +} + func (c CGenPb) Pb(ctx context.Context, in CGenPbInput) (out *CGenPbOutput, err error) { // Necessary check. protoc := gproc.SearchBinary("protoc") if protoc == "" { - mlog.Fatalf(`command "protoc" not found in your environment, please install protoc first to proceed this command`) + mlog.Fatalf(`command "protoc" not found in your environment, please install protoc first: https://grpc.io/docs/languages/go/quickstart/`) } // protocol fold checks. - protoPath := gfile.RealPath(in.Path) + var ( + protoPath = gfile.RealPath(in.Path) + isParsingPWD bool + ) if protoPath == "" { - mlog.Fatalf(`proto files folder "%s" does not exist`, in.Path) + // Use current working directory as protoPath if there are proto files under. + currentPath := gfile.Pwd() + currentFiles, _ := gfile.ScanDirFile(currentPath, "*.proto") + if len(currentFiles) > 0 { + protoPath = currentPath + isParsingPWD = true + } else { + mlog.Fatalf(`proto files folder "%s" does not exist`, in.Path) + } } // output path checks. outputApiPath := gfile.RealPath(in.OutputApi) if outputApiPath == "" { - mlog.Fatalf(`output api folder "%s" does not exist`, in.OutputApi) + if isParsingPWD { + outputApiPath = protoPath + } else { + mlog.Fatalf(`output api folder "%s" does not exist`, in.OutputApi) + } } outputCtrlPath := gfile.RealPath(in.OutputCtrl) if outputCtrlPath == "" { - mlog.Fatalf(`output controller folder "%s" does not exist`, in.OutputCtrl) + if isParsingPWD { + outputCtrlPath = "" + } else { + mlog.Fatalf(`output controller folder "%s" does not exist`, in.OutputCtrl) + } } // folder scanning. @@ -71,12 +108,14 @@ func (c CGenPb) Pb(ctx context.Context, in CGenPbInput) (out *CGenPbOutput, err return } // Generate controllers according comment rules. - err = c.generateController(ctx, generateControllerInput{ - OutputApiPath: outputApiPath, - OutputCtrlPath: outputCtrlPath, - }) - if err != nil { - return + if outputCtrlPath != "" { + err = c.generateController(ctx, generateControllerInput{ + OutputApiPath: outputApiPath, + OutputCtrlPath: outputCtrlPath, + }) + if err != nil { + return + } } mlog.Print("done!") return diff --git a/cmd/gf/internal/cmd/genpbentity/genpbentity.go b/cmd/gf/internal/cmd/genpbentity/genpbentity.go index 22192ea54..b1eb68804 100644 --- a/cmd/gf/internal/cmd/genpbentity/genpbentity.go +++ b/cmd/gf/internal/cmd/genpbentity/genpbentity.go @@ -11,6 +11,7 @@ import ( "github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gregex" @@ -23,7 +24,7 @@ type ( CGenPbEntity struct{} CGenPbEntityInput struct { g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"` - Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}"` + Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"` Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"` Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"` Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"` @@ -37,18 +38,21 @@ type ( CGenPbEntityInternalInput struct { CGenPbEntityInput + DB gdb.DB TableName string // TableName specifies the table name of the table. NewTableName string // NewTableName specifies the prefix-stripped name of the table. } ) const ( - CGenPbEntityConfig = `gfcli.gen.pbentity` - CGenPbEntityBrief = `generate entity message files in protobuf3 format` - CGenPbEntityEg = ` + defaultPackageSuffix = `api/pbentity` + CGenPbEntityConfig = `gfcli.gen.pbentity` + CGenPbEntityBrief = `generate entity message files in protobuf3 format` + CGenPbEntityEg = ` gf gen pbentity gf gen pbentity -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test" gf gen pbentity -p ./protocol/demos/entity -t user,user_detail,user_login +gf gen pbentity -r user_ -k github.com/gogf/gf/example/protobuf gf gen pbentity -r user_ ` @@ -75,8 +79,8 @@ CONFIGURATION SUPPORT option java_package = "protobuf/demos"; option php_namespace = "protobuf/demos"; ` - CGenPbEntityBriefPath = `directory path for generated files` - CGenPbEntityBriefPackage = `package name for all entity proto files` + CGenPbEntityBriefPath = `directory path for generated files storing` + CGenPbEntityBriefPackage = `package path for all entity proto files` CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame` CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','` CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files` @@ -160,7 +164,21 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) } } if in.Package == "" { - mlog.Fatal("package name should not be empty") + mlog.Debug(`package parameter is empty, trying calculating the package path using go.mod`) + if !gfile.Exists("go.mod") { + mlog.Fatal("go.mod does not exist in current working directory") + } + var ( + modName string + goModContent = gfile.GetContents("go.mod") + match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent) + ) + if len(match) > 1 { + modName = gstr.Trim(match[1]) + in.Package = modName + "/" + defaultPackageSuffix + } else { + mlog.Fatal("module name does not found in go.mod") + } } removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",") // It uses user passed database configuration. @@ -198,8 +216,9 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) for _, v := range removePrefixArray { newTableName = gstr.TrimLeftStr(newTableName, v, 1) } - generatePbEntityContentFile(ctx, db, CGenPbEntityInternalInput{ + generatePbEntityContentFile(ctx, CGenPbEntityInternalInput{ CGenPbEntityInput: in, + DB: db, TableName: tableName, NewTableName: newTableName, }) @@ -207,22 +226,28 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput) } // generatePbEntityContentFile generates the protobuf files for given table. -func generatePbEntityContentFile(ctx context.Context, db gdb.DB, in CGenPbEntityInternalInput) { - fieldMap, err := db.TableFields(ctx, in.TableName) +func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInput) { + fieldMap, err := in.DB.TableFields(ctx, in.TableName) if err != nil { mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err) } // Change the `newTableName` if `Prefix` is given. - newTableName := "Entity_" + in.Prefix + in.NewTableName + newTableName := in.Prefix + in.NewTableName var ( + imports string tableNameCamelCase = gstr.CaseCamel(newTableName) tableNameSnakeCase = gstr.CaseSnake(newTableName) entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in) fileName = gstr.Trim(tableNameSnakeCase, "-_.") path = gfile.Join(in.Path, fileName+".proto") ) + if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") { + imports = `import "google/protobuf/timestamp.proto";` + } entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{ - "{PackageName}": in.Package, + "{Imports}": imports, + "{PackageName}": gfile.Basename(in.Package), + "{GoPackage}": in.Package, "{OptionContent}": in.Option, "{EntityMessage}": entityMessageDefine, }) @@ -266,59 +291,38 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb typeName string comment string jsonTagStr string + err error + ctx = gctx.GetInitCtx() ) - t, _ := gregex.ReplaceString(`\(.+\)`, "", field.Type) - t = gstr.Split(gstr.Trim(t), " ")[0] - t = gstr.ToLower(t) - switch t { - case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob": - typeName = "bytes" - - case "bit", "int", "tinyint", "small_int", "smallint", "medium_int", "mediumint", "serial": - if gstr.ContainsI(field.Type, "unsigned") { - typeName = "uint32" - } else { - typeName = "int32" - } - - case "int8", "big_int", "bigint", "bigserial": - if gstr.ContainsI(field.Type, "unsigned") { - typeName = "uint64" - } else { - typeName = "int64" - } - - case "real": - typeName = "float" - - case "float", "double", "decimal", "smallmoney": - typeName = "double" - - case "bool": - typeName = "bool" - - case "datetime", "timestamp", "date", "time": - typeName = "int64" - - default: - // Auto detecting type. - switch { - case strings.Contains(t, "int"): - typeName = "int" - case strings.Contains(t, "text") || strings.Contains(t, "char"): - typeName = "string" - case strings.Contains(t, "float") || strings.Contains(t, "double"): - typeName = "double" - case strings.Contains(t, "bool"): - typeName = "bool" - case strings.Contains(t, "binary") || strings.Contains(t, "blob"): - typeName = "bytes" - case strings.Contains(t, "date") || strings.Contains(t, "time"): - typeName = "int64" - default: - typeName = "string" - } + typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) + if err != nil { + panic(err) } + var typeMapping = map[string]string{ + gdb.LocalTypeString: "string", + gdb.LocalTypeDate: "google.protobuf.Timestamp", + gdb.LocalTypeDatetime: "google.protobuf.Timestamp", + gdb.LocalTypeInt: "int32", + gdb.LocalTypeUint: "uint32", + gdb.LocalTypeInt64: "int64", + gdb.LocalTypeUint64: "uint64", + gdb.LocalTypeIntSlice: "repeated int32", + gdb.LocalTypeInt64Slice: "repeated int64", + gdb.LocalTypeUint64Slice: "repeated uint64", + gdb.LocalTypeInt64Bytes: "repeated int64", + gdb.LocalTypeUint64Bytes: "repeated uint64", + gdb.LocalTypeFloat32: "float32", + gdb.LocalTypeFloat64: "float64", + gdb.LocalTypeBytes: "[]byte", + gdb.LocalTypeBool: "bool", + gdb.LocalTypeJson: "string", + gdb.LocalTypeJsonb: "string", + } + typeName = typeMapping[typeName] + if typeName == "" { + typeName = "string" + } + comment = gstr.ReplaceByArray(field.Comment, g.SliceStr{ "\n", " ", "\r", " ", @@ -327,7 +331,6 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb comment = gstr.Replace(comment, `\n`, " ") comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment) if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" { - jsonTagStr = fmt.Sprintf(`[(gogoproto.jsontag) = "%s"]`, jsonTagName) // beautiful indent. if index < 10 { // 3 spaces diff --git a/cmd/gf/internal/consts/consts_gen_pbentity_template.go b/cmd/gf/internal/consts/consts_gen_pbentity_template.go index bbb184a38..922b48719 100644 --- a/cmd/gf/internal/consts/consts_gen_pbentity_template.go +++ b/cmd/gf/internal/consts/consts_gen_pbentity_template.go @@ -9,9 +9,9 @@ syntax = "proto3"; package {PackageName}; -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; - +option go_package = "{GoPackage}"; {OptionContent} +{Imports} {EntityMessage} ` diff --git a/cmd/gf/internal/packed/template-mono.go b/cmd/gf/internal/packed/template-mono.go index 856c4afd9..00fd3e47a 100644 --- a/cmd/gf/internal/packed/template-mono.go +++ b/cmd/gf/internal/packed/template-mono.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/cmd/gf/internal/packed/template-single.go b/cmd/gf/internal/packed/template-single.go index afac2f55c..58a99f286 100644 --- a/cmd/gf/internal/packed/template-single.go +++ b/cmd/gf/internal/packed/template-single.go @@ -3,7 +3,7 @@ package packed import "github.com/gogf/gf/v2/os/gres" func init() { - if err := gres.Add("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"); err != nil { + if err := gres.Add("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"); err != nil { panic("add binary content to resource manager failed: " + err.Error()) } } diff --git a/contrib/config/polaris/polaris.go b/contrib/config/polaris/polaris.go index 6944bc291..589b0ca4c 100644 --- a/contrib/config/polaris/polaris.go +++ b/contrib/config/polaris/polaris.go @@ -10,14 +10,15 @@ package polaris import ( "context" + "github.com/polarismesh/polaris-go" + "github.com/polarismesh/polaris-go/api" + "github.com/polarismesh/polaris-go/pkg/model" + "github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcfg" "github.com/gogf/gf/v2/text/gstr" - "github.com/polarismesh/polaris-go" - "github.com/polarismesh/polaris-go/api" - "github.com/polarismesh/polaris-go/pkg/model" ) // LogDir sets the log directory for polaris. @@ -65,7 +66,7 @@ func New(ctx context.Context, config Config) (adapter gcfg.Adapter, err error) { ) if configAPI, err = polaris.NewConfigAPIByFile(config.Path); err != nil { - err = gerror.Wrapf(err, "Polaris configuration initialization failed with config: %+v", config) + err = gerror.Wrapf(err, "Polaris configuration initialization failed with config: %+v", config) return } // set log dir diff --git a/contrib/rpc/grpcx/grpcx_registry_file.go b/contrib/rpc/grpcx/grpcx_registry_file.go index 8886f9641..c1b0961fe 100644 --- a/contrib/rpc/grpcx/grpcx_registry_file.go +++ b/contrib/rpc/grpcx/grpcx_registry_file.go @@ -13,8 +13,6 @@ import ( "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gctx" "github.com/gogf/gf/v2/os/gfile" - - "github.com/gogf/gf/contrib/rpc/grpcx/v2/internal/resolver" ) // autoLoadAndRegisterFileRegistry checks and registers ETCD service as default service registry @@ -30,5 +28,5 @@ func autoLoadAndRegisterFileRegistry() { ) g.Log().Debug(ctx, `set default registry using file registry as no custom registry set`) - resolver.SetRegistry(fileRegistry) + Resolver.Register(fileRegistry) } diff --git a/contrib/rpc/grpcx/internal/resolver/resolver.go b/contrib/rpc/grpcx/internal/resolver/resolver.go index 3be402685..38d89f1a6 100644 --- a/contrib/rpc/grpcx/internal/resolver/resolver.go +++ b/contrib/rpc/grpcx/internal/resolver/resolver.go @@ -25,8 +25,8 @@ func init() { resolver.Register(NewBuilder(gsvc.GetRegistry())) } -// SetRegistry sets the default Registry implements as your own implemented interface. -func SetRegistry(registry gsvc.Registry) { +// Register sets the default Registry implements as your own implemented interface. +func Register(registry gsvc.Registry) { if registry == nil { panic(gerror.New(`invalid Registry value "nil" given`)) } diff --git a/contrib/rpc/grpcx/internal/resolver/resolver_manager.go b/contrib/rpc/grpcx/internal/resolver/resolver_manager.go index d9ea97716..b18e96713 100644 --- a/contrib/rpc/grpcx/internal/resolver/resolver_manager.go +++ b/contrib/rpc/grpcx/internal/resolver/resolver_manager.go @@ -15,6 +15,12 @@ import ( // Manager for Builder creating. type Manager struct{} +// New creates and returns a Builder. func (m Manager) New(discovery gsvc.Discovery) resolver.Builder { return NewBuilder(discovery) } + +// Register sets the default Registry implements as your own implemented interface. +func (m Manager) Register(registry gsvc.Registry) { + Register(registry) +} diff --git a/example/registry/etcd/client/main.go b/example/balancer/http/client/client.go similarity index 57% rename from example/registry/etcd/client/main.go rename to example/balancer/http/client/client.go index fd539db70..7d615d493 100644 --- a/example/registry/etcd/client/main.go +++ b/example/balancer/http/client/client.go @@ -1,9 +1,6 @@ package main import ( - "fmt" - "time" - "github.com/gogf/gf/contrib/registry/etcd/v2" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gsel" @@ -15,14 +12,9 @@ func main() { gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`)) gsel.SetBuilder(gsel.NewBuilderRoundRobin()) - client := g.Client() - for i := 0; i < 100; i++ { - res, err := client.Get(gctx.New(), `http://hello.svc/`) - if err != nil { - panic(err) - } - fmt.Println(res.ReadAllString()) - res.Close() - time.Sleep(time.Second) + for i := 0; i < 10; i++ { + ctx := gctx.New() + res := g.Client().GetContent(ctx, `http://hello.svc/`) + g.Log().Info(ctx, res) } } diff --git a/example/registry/etcd/server/main.go b/example/balancer/http/server/server.go similarity index 100% rename from example/registry/etcd/server/main.go rename to example/balancer/http/server/server.go diff --git a/example/config/polaris/boot/boot.go b/example/config/polaris/boot/boot.go index f5f3a2f19..a41101d93 100644 --- a/example/config/polaris/boot/boot.go +++ b/example/config/polaris/boot/boot.go @@ -10,9 +10,9 @@ func init() { var ( ctx = gctx.GetInitCtx() namespace = "default" - fileGroup = "goframe" + fileGroup = "TestGroup" fileName = "config.yaml" - path = "testdata/polaris.yaml" + path = "manifest/config/polaris.yaml" logDir = "/tmp/polaris/log" ) // Create polaris Client that implements gcfg.Adapter. diff --git a/example/config/polaris/main.go b/example/config/polaris/main.go index a23632206..7939e73f7 100644 --- a/example/config/polaris/main.go +++ b/example/config/polaris/main.go @@ -1,4 +1,4 @@ -package polaris +package main import ( _ "github.com/gogf/gf/example/config/polaris/boot" diff --git a/example/config/polaris/testdata/polaris.yaml b/example/config/polaris/testdata/polaris.yaml index 9f785c233..c6e747f27 100644 --- a/example/config/polaris/testdata/polaris.yaml +++ b/example/config/polaris/testdata/polaris.yaml @@ -1,11 +1,11 @@ global: serverConnector: addresses: - - 183.47.111.80:8091 + - 127.0.0.1:8091 config: configConnector: addresses: - - 183.47.111.80:8093 + - 127.0.0.1:8093 consumer: localCache: persistDir: "/tmp/polaris/backup" \ No newline at end of file diff --git a/example/registry/etcd/grpc/client/client.go b/example/registry/etcd/grpc/client/client.go new file mode 100644 index 000000000..17293ac61 --- /dev/null +++ b/example/registry/etcd/grpc/client/client.go @@ -0,0 +1,31 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/registry/etcd/grpc/protobuf" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + + var ( + ctx = gctx.New() + conn = grpcx.Client.MustNewGrpcClientConn("demo") + client = protobuf.NewGreeterClient(conn) + ) + res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"}) + if err != nil { + g.Log().Error(ctx, err) + return + } + g.Log().Debug(ctx, "Response:", res.Message) +} diff --git a/example/registry/etcd/grpc/controller/helloworld.go b/example/registry/etcd/grpc/controller/helloworld.go new file mode 100644 index 000000000..86aa46c9a --- /dev/null +++ b/example/registry/etcd/grpc/controller/helloworld.go @@ -0,0 +1,27 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package controller + +import ( + "context" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/registry/etcd/grpc/protobuf" +) + +type Controller struct { + protobuf.UnimplementedGreeterServer +} + +func Register(s *grpcx.GrpcServer) { + protobuf.RegisterGreeterServer(s.Server, &Controller{}) +} + +// SayHello implements helloworld.GreeterServer +func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) { + return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/example/registry/etcd/grpc/protobuf/helloworld.pb.go b/example/registry/etcd/grpc/protobuf/helloworld.pb.go new file mode 100644 index 000000000..8af3b213b --- /dev/null +++ b/example/registry/etcd/grpc/protobuf/helloworld.pb.go @@ -0,0 +1,217 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x22, 0x0a, 0x0c, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x45, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, + 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, + 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x67, 0x66, 0x2f, 0x67, 0x66, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protobuf.HelloRequest + (*HelloReply)(nil), // 1: protobuf.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: protobuf.Greeter.SayHello:input_type -> protobuf.HelloRequest + 1, // 1: protobuf.Greeter.SayHello:output_type -> protobuf.HelloReply + 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_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); 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_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/example/registry/etcd/grpc/protobuf/helloworld.proto b/example/registry/etcd/grpc/protobuf/helloworld.proto new file mode 100644 index 000000000..9f4f4864f --- /dev/null +++ b/example/registry/etcd/grpc/protobuf/helloworld.proto @@ -0,0 +1,24 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +syntax = "proto3"; + +package protobuf; + +option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/example/registry/etcd/grpc/protobuf/helloworld_grpc.pb.go b/example/registry/etcd/grpc/protobuf/helloworld_grpc.pb.go new file mode 100644 index 000000000..af29539f4 --- /dev/null +++ b/example/registry/etcd/grpc/protobuf/helloworld_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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 + +// GreeterClient is the client API for Greeter 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 GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/protobuf.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "protobuf.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/example/rpc/grpcx/basic_with_tag/server/config.yaml b/example/registry/etcd/grpc/server/config.yaml similarity index 100% rename from example/rpc/grpcx/basic_with_tag/server/config.yaml rename to example/registry/etcd/grpc/server/config.yaml diff --git a/example/rpc/grpcx/basic_with_tag/server/main.go b/example/registry/etcd/grpc/server/server.go similarity index 67% rename from example/rpc/grpcx/basic_with_tag/server/main.go rename to example/registry/etcd/grpc/server/server.go index 6f91533a8..6fdb2124b 100644 --- a/example/rpc/grpcx/basic_with_tag/server/main.go +++ b/example/registry/etcd/grpc/server/server.go @@ -7,13 +7,15 @@ package main import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" "github.com/gogf/gf/contrib/rpc/grpcx/v2" - "github.com/gogf/gf/example/rpc/grpcx/basic_with_tag/protocol" - "github.com/gogf/gf/example/rpc/grpcx/basic_with_tag/service" + "github.com/gogf/gf/example/registry/etcd/grpc/controller" ) func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + s := grpcx.Server.New() - protocol.RegisterEchoServer(s.Server, new(service.Echo)) + controller.Register(s) s.Run() } diff --git a/example/registry/etcd/http/client/client.go b/example/registry/etcd/http/client/client.go new file mode 100644 index 000000000..e5675b829 --- /dev/null +++ b/example/registry/etcd/http/client/client.go @@ -0,0 +1,15 @@ +package main + +import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/gsvc" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`)) + ctx := gctx.New() + res := g.Client().GetContent(ctx, `http://hello.svc/`) + g.Log().Info(ctx, res) +} diff --git a/example/registry/etcd/http/server/server.go b/example/registry/etcd/http/server/server.go new file mode 100644 index 000000000..355d9cbb0 --- /dev/null +++ b/example/registry/etcd/http/server/server.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/net/gsvc" +) + +func main() { + gsvc.SetRegistry(etcd.New(`127.0.0.1:2379`)) + + s := g.Server(`hello.svc`) + s.BindHandler("/", func(r *ghttp.Request) { + g.Log().Info(r.Context(), `request received`) + r.Response.Write(`Hello world`) + }) + s.Run() +} diff --git a/example/registry/file/client/main.go b/example/registry/file/client/client.go similarity index 73% rename from example/registry/file/client/main.go rename to example/registry/file/client/client.go index 8929a5554..1f32cc3eb 100644 --- a/example/registry/file/client/main.go +++ b/example/registry/file/client/client.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "time" "github.com/gogf/gf/contrib/registry/file/v2" @@ -15,12 +14,13 @@ func main() { gsvc.SetRegistry(file.New(gfile.Temp("gsvc"))) client := g.Client() - for i := 0; i < 100; i++ { - res, err := client.Get(gctx.New(), `http://hello.svc/`) + for i := 0; i < 10; i++ { + ctx := gctx.New() + res, err := client.Get(ctx, `http://hello.svc/`) if err != nil { panic(err) } - fmt.Println(res.ReadAllString()) + g.Log().Debug(ctx, res.ReadAllString()) res.Close() time.Sleep(time.Second) } diff --git a/example/registry/file/server/main.go b/example/registry/file/server/server.go similarity index 100% rename from example/registry/file/server/main.go rename to example/registry/file/server/server.go diff --git a/example/registry/polaris/client/main.go b/example/registry/polaris/client/client.go similarity index 99% rename from example/registry/polaris/client/main.go rename to example/registry/polaris/client/client.go index 03ca7a6b7..7be0f412e 100644 --- a/example/registry/polaris/client/main.go +++ b/example/registry/polaris/client/client.go @@ -5,12 +5,13 @@ import ( "fmt" "time" + "github.com/polarismesh/polaris-go/api" + "github.com/polarismesh/polaris-go/pkg/config" + "github.com/gogf/gf/contrib/registry/polaris/v2" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/os/gctx" - "github.com/polarismesh/polaris-go/api" - "github.com/polarismesh/polaris-go/pkg/config" ) func main() { diff --git a/example/registry/polaris/server/main.go b/example/registry/polaris/server/server.go similarity index 100% rename from example/registry/polaris/server/main.go rename to example/registry/polaris/server/server.go diff --git a/example/rpc/grpcx/basic/client/main.go b/example/rpc/grpcx/balancer/client/client.go similarity index 55% rename from example/rpc/grpcx/basic/client/main.go rename to example/rpc/grpcx/balancer/client/client.go index f747162af..5a3ba518c 100644 --- a/example/rpc/grpcx/basic/client/main.go +++ b/example/rpc/grpcx/balancer/client/client.go @@ -7,26 +7,27 @@ package main import ( - "time" + "context" "github.com/gogf/gf/contrib/rpc/grpcx/v2" - "github.com/gogf/gf/example/rpc/grpcx/basic/protocol" + "github.com/gogf/gf/example/rpc/grpcx/balancer/protobuf" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" ) func main() { var ( - ctx = gctx.GetInitCtx() - client = protocol.NewEchoClient(grpcx.Client.MustNewGrpcClientConn("demo")) + ctx context.Context + conn = grpcx.Client.MustNewGrpcClientConn("demo", grpcx.Balancer.WithRandom()) + client = protobuf.NewGreeterClient(conn) ) - for i := 0; i < 100; i++ { - res, err := client.Say(ctx, &protocol.SayReq{Content: "Hello"}) + for i := 0; i < 10; i++ { + ctx = gctx.New() + res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"}) if err != nil { g.Log().Error(ctx, err) return } - g.Log().Print(ctx, "Response:", res.Content) - time.Sleep(time.Second) + g.Log().Debug(ctx, "Response:", res.Message) } } diff --git a/example/rpc/grpcx/balancer/controller/helloworld.go b/example/rpc/grpcx/balancer/controller/helloworld.go new file mode 100644 index 000000000..e30161523 --- /dev/null +++ b/example/rpc/grpcx/balancer/controller/helloworld.go @@ -0,0 +1,27 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package controller + +import ( + "context" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/balancer/protobuf" +) + +type Controller struct { + protobuf.UnimplementedGreeterServer +} + +func Register(s *grpcx.GrpcServer) { + protobuf.RegisterGreeterServer(s.Server, &Controller{}) +} + +// SayHello implements helloworld.GreeterServer +func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) { + return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/example/rpc/grpcx/balancer/protobuf/helloworld.pb.go b/example/rpc/grpcx/balancer/protobuf/helloworld.pb.go new file mode 100644 index 000000000..8af3b213b --- /dev/null +++ b/example/rpc/grpcx/balancer/protobuf/helloworld.pb.go @@ -0,0 +1,217 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x22, 0x0a, 0x0c, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x45, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, + 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, + 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x67, 0x66, 0x2f, 0x67, 0x66, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protobuf.HelloRequest + (*HelloReply)(nil), // 1: protobuf.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: protobuf.Greeter.SayHello:input_type -> protobuf.HelloRequest + 1, // 1: protobuf.Greeter.SayHello:output_type -> protobuf.HelloReply + 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_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); 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_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/example/rpc/grpcx/balancer/protobuf/helloworld.proto b/example/rpc/grpcx/balancer/protobuf/helloworld.proto new file mode 100644 index 000000000..9f4f4864f --- /dev/null +++ b/example/rpc/grpcx/balancer/protobuf/helloworld.proto @@ -0,0 +1,24 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +syntax = "proto3"; + +package protobuf; + +option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/example/rpc/grpcx/balancer/protobuf/helloworld_grpc.pb.go b/example/rpc/grpcx/balancer/protobuf/helloworld_grpc.pb.go new file mode 100644 index 000000000..af29539f4 --- /dev/null +++ b/example/rpc/grpcx/balancer/protobuf/helloworld_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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 + +// GreeterClient is the client API for Greeter 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 GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/protobuf.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "protobuf.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/example/rpc/grpcx/balancer/server/config.yaml b/example/rpc/grpcx/balancer/server/config.yaml new file mode 100644 index 000000000..071b62623 --- /dev/null +++ b/example/rpc/grpcx/balancer/server/config.yaml @@ -0,0 +1,8 @@ +grpc: + name: "demo" + logPath: "./log" + logStdout: true + errorLogEnabled: true + accessLogEnabled: true + errorStack: true + diff --git a/example/rpc/grpcx/basic/server/main.go b/example/rpc/grpcx/balancer/server/server.go similarity index 69% rename from example/rpc/grpcx/basic/server/main.go rename to example/rpc/grpcx/balancer/server/server.go index f420fd070..0a938c599 100644 --- a/example/rpc/grpcx/basic/server/main.go +++ b/example/rpc/grpcx/balancer/server/server.go @@ -8,12 +8,11 @@ package main import ( "github.com/gogf/gf/contrib/rpc/grpcx/v2" - "github.com/gogf/gf/example/rpc/grpcx/basic/protocol" - "github.com/gogf/gf/example/rpc/grpcx/basic/service" + "github.com/gogf/gf/example/rpc/grpcx/balancer/controller" ) func main() { s := grpcx.Server.New() - protocol.RegisterEchoServer(s.Server, new(service.Echo)) + controller.Register(s) s.Run() } diff --git a/example/rpc/grpcx/basic/client/client.go b/example/rpc/grpcx/basic/client/client.go new file mode 100644 index 000000000..f2779bf86 --- /dev/null +++ b/example/rpc/grpcx/basic/client/client.go @@ -0,0 +1,28 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/basic/protobuf" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + var ( + ctx = gctx.New() + conn = grpcx.Client.MustNewGrpcClientConn("demo") + client = protobuf.NewGreeterClient(conn) + ) + res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"}) + if err != nil { + g.Log().Error(ctx, err) + return + } + g.Log().Debug(ctx, "Response:", res.Message) +} diff --git a/example/rpc/grpcx/basic/client/config.yaml b/example/rpc/grpcx/basic/client/config.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/example/rpc/grpcx/basic/controller/helloworld.go b/example/rpc/grpcx/basic/controller/helloworld.go new file mode 100644 index 000000000..4441e5fd0 --- /dev/null +++ b/example/rpc/grpcx/basic/controller/helloworld.go @@ -0,0 +1,27 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package controller + +import ( + "context" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/basic/protobuf" +) + +type Controller struct { + protobuf.UnimplementedGreeterServer +} + +func Register(s *grpcx.GrpcServer) { + protobuf.RegisterGreeterServer(s.Server, &Controller{}) +} + +// SayHello implements helloworld.GreeterServer +func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) { + return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/example/rpc/grpcx/basic/protobuf/echo.proto b/example/rpc/grpcx/basic/protobuf/echo.proto deleted file mode 100644 index d13b3ed41..000000000 --- a/example/rpc/grpcx/basic/protobuf/echo.proto +++ /dev/null @@ -1,21 +0,0 @@ -// protoc --go_out=plugins=grpc:. *.proto - -syntax = "proto3"; - -package proto; - -option go_package = "/proto"; - -service Echo{ - rpc Say(SayReq) returns (SayRes) {} -} - -message SayReq { - string content = 1; -} - -message SayRes { - string content = 1; -} - - diff --git a/example/rpc/grpcx/basic/protobuf/helloworld.pb.go b/example/rpc/grpcx/basic/protobuf/helloworld.pb.go new file mode 100644 index 000000000..8af3b213b --- /dev/null +++ b/example/rpc/grpcx/basic/protobuf/helloworld.pb.go @@ -0,0 +1,217 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x22, 0x0a, 0x0c, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x45, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, + 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, + 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x67, 0x66, 0x2f, 0x67, 0x66, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protobuf.HelloRequest + (*HelloReply)(nil), // 1: protobuf.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: protobuf.Greeter.SayHello:input_type -> protobuf.HelloRequest + 1, // 1: protobuf.Greeter.SayHello:output_type -> protobuf.HelloReply + 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_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); 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_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/example/rpc/grpcx/basic/protobuf/helloworld.proto b/example/rpc/grpcx/basic/protobuf/helloworld.proto new file mode 100644 index 000000000..9f4f4864f --- /dev/null +++ b/example/rpc/grpcx/basic/protobuf/helloworld.proto @@ -0,0 +1,24 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +syntax = "proto3"; + +package protobuf; + +option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/example/rpc/grpcx/basic/protobuf/helloworld_grpc.pb.go b/example/rpc/grpcx/basic/protobuf/helloworld_grpc.pb.go new file mode 100644 index 000000000..af29539f4 --- /dev/null +++ b/example/rpc/grpcx/basic/protobuf/helloworld_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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 + +// GreeterClient is the client API for Greeter 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 GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/protobuf.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "protobuf.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/example/rpc/grpcx/basic/protocol/echo.pb.go b/example/rpc/grpcx/basic/protocol/echo.pb.go deleted file mode 100644 index c6753d6f2..000000000 --- a/example/rpc/grpcx/basic/protocol/echo.pb.go +++ /dev/null @@ -1,305 +0,0 @@ -// protoc --go_out=plugins=grpc:. *.proto - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.23.0 -// protoc v3.11.4 -// source: echo.proto - -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package protocol - -import ( - context "context" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type SayReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` -} - -func (x *SayReq) Reset() { - *x = SayReq{} - if protoimpl.UnsafeEnabled { - mi := &file_echo_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SayReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SayReq) ProtoMessage() {} - -func (x *SayReq) ProtoReflect() protoreflect.Message { - mi := &file_echo_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 SayReq.ProtoReflect.Descriptor instead. -func (*SayReq) Descriptor() ([]byte, []int) { - return file_echo_proto_rawDescGZIP(), []int{0} -} - -func (x *SayReq) GetContent() string { - if x != nil { - return x.Content - } - return "" -} - -type SayRes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` -} - -func (x *SayRes) Reset() { - *x = SayRes{} - if protoimpl.UnsafeEnabled { - mi := &file_echo_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SayRes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SayRes) ProtoMessage() {} - -func (x *SayRes) ProtoReflect() protoreflect.Message { - mi := &file_echo_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 SayRes.ProtoReflect.Descriptor instead. -func (*SayRes) Descriptor() ([]byte, []int) { - return file_echo_proto_rawDescGZIP(), []int{1} -} - -func (x *SayRes) GetContent() string { - if x != nil { - return x.Content - } - return "" -} - -var File_echo_proto protoreflect.FileDescriptor - -var file_echo_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, 0x06, 0x53, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x22, 0x0a, 0x06, 0x53, 0x61, 0x79, 0x52, 0x65, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x32, 0x2d, 0x0a, 0x04, 0x45, - 0x63, 0x68, 0x6f, 0x12, 0x25, 0x0a, 0x03, 0x53, 0x61, 0x79, 0x12, 0x0d, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x53, 0x61, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_echo_proto_rawDescOnce sync.Once - file_echo_proto_rawDescData = file_echo_proto_rawDesc -) - -func file_echo_proto_rawDescGZIP() []byte { - file_echo_proto_rawDescOnce.Do(func() { - file_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_echo_proto_rawDescData) - }) - return file_echo_proto_rawDescData -} - -var file_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_echo_proto_goTypes = []interface{}{ - (*SayReq)(nil), // 0: proto.SayReq - (*SayRes)(nil), // 1: proto.SayRes -} -var file_echo_proto_depIdxs = []int32{ - 0, // 0: proto.Echo.Say:input_type -> proto.SayReq - 1, // 1: proto.Echo.Say:output_type -> proto.SayRes - 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_echo_proto_init() } -func file_echo_proto_init() { - if File_echo_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_echo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SayReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_echo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SayRes); 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_echo_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_echo_proto_goTypes, - DependencyIndexes: file_echo_proto_depIdxs, - MessageInfos: file_echo_proto_msgTypes, - }.Build() - File_echo_proto = out.File - file_echo_proto_rawDesc = nil - file_echo_proto_goTypes = nil - file_echo_proto_depIdxs = nil -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// EchoClient is the client API for Echo service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type EchoClient interface { - Say(ctx context.Context, in *SayReq, opts ...grpc.CallOption) (*SayRes, error) -} - -type echoClient struct { - cc grpc.ClientConnInterface -} - -func NewEchoClient(cc grpc.ClientConnInterface) EchoClient { - return &echoClient{cc} -} - -func (c *echoClient) Say(ctx context.Context, in *SayReq, opts ...grpc.CallOption) (*SayRes, error) { - out := new(SayRes) - err := c.cc.Invoke(ctx, "/proto.Echo/Say", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// EchoServer is the server API for Echo service. -type EchoServer interface { - Say(context.Context, *SayReq) (*SayRes, error) -} - -// UnimplementedEchoServer can be embedded to have forward compatible implementations. -type UnimplementedEchoServer struct { -} - -func (*UnimplementedEchoServer) Say(context.Context, *SayReq) (*SayRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Say not implemented") -} - -func RegisterEchoServer(s *grpc.Server, srv EchoServer) { - s.RegisterService(&_Echo_serviceDesc, srv) -} - -func _Echo_Say_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SayReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(EchoServer).Say(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/proto.Echo/Say", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EchoServer).Say(ctx, req.(*SayReq)) - } - return interceptor(ctx, in, info, handler) -} - -var _Echo_serviceDesc = grpc.ServiceDesc{ - ServiceName: "proto.Echo", - HandlerType: (*EchoServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Say", - Handler: _Echo_Say_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "echo.proto", -} diff --git a/example/rpc/grpcx/basic/server/server.go b/example/rpc/grpcx/basic/server/server.go new file mode 100644 index 000000000..5afdeb44c --- /dev/null +++ b/example/rpc/grpcx/basic/server/server.go @@ -0,0 +1,18 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/basic/controller" +) + +func main() { + s := grpcx.Server.New() + controller.Register(s) + s.Run() +} diff --git a/example/rpc/grpcx/basic/service/service_echo.go b/example/rpc/grpcx/basic/service/service_echo.go deleted file mode 100644 index d66f5ab23..000000000 --- a/example/rpc/grpcx/basic/service/service_echo.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package service - -import ( - "fmt" - - "context" - - "github.com/gogf/gf/example/rpc/grpcx/basic/protocol" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gcmd" -) - -// Echo is the service for echo. -type Echo struct{} - -// Say implements the protobuf.EchoServer interface. -func (s *Echo) Say(ctx context.Context, r *protocol.SayReq) (*protocol.SayRes, error) { - g.Log().Print(ctx, "Received:", r.Content) - text := fmt.Sprintf(`%s: > %s`, gcmd.GetOpt("node", "default"), r.Content) - return &protocol.SayRes{Content: text}, nil -} diff --git a/example/rpc/grpcx/basic_with_tag/client/config.yaml b/example/rpc/grpcx/basic_with_tag/client/config.yaml deleted file mode 100644 index e69de29bb..000000000 diff --git a/example/rpc/grpcx/basic_with_tag/client/main.go b/example/rpc/grpcx/basic_with_tag/client/main.go deleted file mode 100644 index c4079e31c..000000000 --- a/example/rpc/grpcx/basic_with_tag/client/main.go +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package main - -import ( - "time" - - "github.com/gogf/gf/example/rpc/grpcx/basic_with_tag/protocol" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gctx" -) - -func main() { - var ( - ctx = gctx.GetInitCtx() - client, err = protocol.NewClient() - ) - if err != nil { - g.Log().Fatalf(ctx, `%+v`, err) - } - for i := 0; i < 100; i++ { - res, err := client.Echo().Say(ctx, &protocol.SayReq{Content: "Hello"}) - if err != nil { - g.Log().Error(ctx, err) - return - } - g.Log().Print(ctx, "Response:", res.Content) - time.Sleep(time.Second) - } -} diff --git a/example/rpc/grpcx/basic_with_tag/protobuf/echo.proto b/example/rpc/grpcx/basic_with_tag/protobuf/echo.proto deleted file mode 100644 index 6a3d3e1cf..000000000 --- a/example/rpc/grpcx/basic_with_tag/protobuf/echo.proto +++ /dev/null @@ -1,19 +0,0 @@ -// protoc --go_out=plugins=grpc:. *.proto - -syntax = "proto3"; - -package proto; - -service Echo{ - rpc Say(SayReq) returns (SayRes) {} -} - -message SayReq { - string content = 1; -} - -message SayRes { - string content = 1; -} - - diff --git a/example/rpc/grpcx/basic_with_tag/protocol/client.go b/example/rpc/grpcx/basic_with_tag/protocol/client.go deleted file mode 100644 index 1177da05e..000000000 --- a/example/rpc/grpcx/basic_with_tag/protocol/client.go +++ /dev/null @@ -1,31 +0,0 @@ -package protocol - -import ( - "google.golang.org/grpc" - - "github.com/gogf/gf/contrib/rpc/grpcx/v2" -) - -const ( - // AppID is the application ID for the protobuf service. - AppID = "demo" -) - -// Client is the client for protobuf. -type Client struct { - conn *grpc.ClientConn -} - -// NewClient creates and returns a new client. -func NewClient(options ...grpc.DialOption) (*Client, error) { - conn, err := grpcx.Client.NewGrpcClientConn(AppID, options...) - if err != nil { - return nil, err - } - return &Client{conn: conn}, nil -} - -// Echo is the client for protobuf.Echo. -func (c *Client) Echo() EchoClient { - return NewEchoClient(c.conn) -} diff --git a/example/rpc/grpcx/basic_with_tag/protocol/echo.pb.go b/example/rpc/grpcx/basic_with_tag/protocol/echo.pb.go deleted file mode 100644 index c6753d6f2..000000000 --- a/example/rpc/grpcx/basic_with_tag/protocol/echo.pb.go +++ /dev/null @@ -1,305 +0,0 @@ -// protoc --go_out=plugins=grpc:. *.proto - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.23.0 -// protoc v3.11.4 -// source: echo.proto - -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package protocol - -import ( - context "context" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -type SayReq struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` -} - -func (x *SayReq) Reset() { - *x = SayReq{} - if protoimpl.UnsafeEnabled { - mi := &file_echo_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SayReq) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SayReq) ProtoMessage() {} - -func (x *SayReq) ProtoReflect() protoreflect.Message { - mi := &file_echo_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 SayReq.ProtoReflect.Descriptor instead. -func (*SayReq) Descriptor() ([]byte, []int) { - return file_echo_proto_rawDescGZIP(), []int{0} -} - -func (x *SayReq) GetContent() string { - if x != nil { - return x.Content - } - return "" -} - -type SayRes struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Content string `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` -} - -func (x *SayRes) Reset() { - *x = SayRes{} - if protoimpl.UnsafeEnabled { - mi := &file_echo_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SayRes) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SayRes) ProtoMessage() {} - -func (x *SayRes) ProtoReflect() protoreflect.Message { - mi := &file_echo_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 SayRes.ProtoReflect.Descriptor instead. -func (*SayRes) Descriptor() ([]byte, []int) { - return file_echo_proto_rawDescGZIP(), []int{1} -} - -func (x *SayRes) GetContent() string { - if x != nil { - return x.Content - } - return "" -} - -var File_echo_proto protoreflect.FileDescriptor - -var file_echo_proto_rawDesc = []byte{ - 0x0a, 0x0a, 0x65, 0x63, 0x68, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x22, 0x22, 0x0a, 0x06, 0x53, 0x61, 0x79, 0x52, 0x65, 0x71, 0x12, 0x18, 0x0a, - 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x22, 0x0a, 0x06, 0x53, 0x61, 0x79, 0x52, 0x65, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x32, 0x2d, 0x0a, 0x04, 0x45, - 0x63, 0x68, 0x6f, 0x12, 0x25, 0x0a, 0x03, 0x53, 0x61, 0x79, 0x12, 0x0d, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2e, 0x53, 0x61, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2e, 0x53, 0x61, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, -} - -var ( - file_echo_proto_rawDescOnce sync.Once - file_echo_proto_rawDescData = file_echo_proto_rawDesc -) - -func file_echo_proto_rawDescGZIP() []byte { - file_echo_proto_rawDescOnce.Do(func() { - file_echo_proto_rawDescData = protoimpl.X.CompressGZIP(file_echo_proto_rawDescData) - }) - return file_echo_proto_rawDescData -} - -var file_echo_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_echo_proto_goTypes = []interface{}{ - (*SayReq)(nil), // 0: proto.SayReq - (*SayRes)(nil), // 1: proto.SayRes -} -var file_echo_proto_depIdxs = []int32{ - 0, // 0: proto.Echo.Say:input_type -> proto.SayReq - 1, // 1: proto.Echo.Say:output_type -> proto.SayRes - 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_echo_proto_init() } -func file_echo_proto_init() { - if File_echo_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_echo_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SayReq); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_echo_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SayRes); 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_echo_proto_rawDesc, - NumEnums: 0, - NumMessages: 2, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_echo_proto_goTypes, - DependencyIndexes: file_echo_proto_depIdxs, - MessageInfos: file_echo_proto_msgTypes, - }.Build() - File_echo_proto = out.File - file_echo_proto_rawDesc = nil - file_echo_proto_goTypes = nil - file_echo_proto_depIdxs = nil -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConnInterface - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion6 - -// EchoClient is the client API for Echo service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type EchoClient interface { - Say(ctx context.Context, in *SayReq, opts ...grpc.CallOption) (*SayRes, error) -} - -type echoClient struct { - cc grpc.ClientConnInterface -} - -func NewEchoClient(cc grpc.ClientConnInterface) EchoClient { - return &echoClient{cc} -} - -func (c *echoClient) Say(ctx context.Context, in *SayReq, opts ...grpc.CallOption) (*SayRes, error) { - out := new(SayRes) - err := c.cc.Invoke(ctx, "/proto.Echo/Say", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// EchoServer is the server API for Echo service. -type EchoServer interface { - Say(context.Context, *SayReq) (*SayRes, error) -} - -// UnimplementedEchoServer can be embedded to have forward compatible implementations. -type UnimplementedEchoServer struct { -} - -func (*UnimplementedEchoServer) Say(context.Context, *SayReq) (*SayRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Say not implemented") -} - -func RegisterEchoServer(s *grpc.Server, srv EchoServer) { - s.RegisterService(&_Echo_serviceDesc, srv) -} - -func _Echo_Say_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SayReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(EchoServer).Say(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/proto.Echo/Say", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(EchoServer).Say(ctx, req.(*SayReq)) - } - return interceptor(ctx, in, info, handler) -} - -var _Echo_serviceDesc = grpc.ServiceDesc{ - ServiceName: "proto.Echo", - HandlerType: (*EchoServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Say", - Handler: _Echo_Say_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "echo.proto", -} diff --git a/example/rpc/grpcx/basic_with_tag/service/service_echo.go b/example/rpc/grpcx/basic_with_tag/service/service_echo.go deleted file mode 100644 index c18d8b8d1..000000000 --- a/example/rpc/grpcx/basic_with_tag/service/service_echo.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. -// -// This Source Code Form is subject to the terms of the MIT License. -// If a copy of the MIT was not distributed with this file, -// You can obtain one at https://github.com/gogf/gf. - -package service - -import ( - "fmt" - - "context" - - "github.com/gogf/gf/example/rpc/grpcx/basic_with_tag/protocol" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gcmd" -) - -// Echo is the service for echo. -type Echo struct{} - -// Say implements the protobuf.EchoServer interface. -func (s *Echo) Say(ctx context.Context, r *protocol.SayReq) (*protocol.SayRes, error) { - g.Log().Print(ctx, "Received:", r.Content) - text := fmt.Sprintf(`%s: > %s`, gcmd.GetOpt("node", "default"), r.Content) - return &protocol.SayRes{Content: text}, nil -} diff --git a/example/rpc/grpcx/ctx/client/client.go b/example/rpc/grpcx/ctx/client/client.go new file mode 100644 index 000000000..1ce674329 --- /dev/null +++ b/example/rpc/grpcx/ctx/client/client.go @@ -0,0 +1,32 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/ctx/protobuf" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + var ( + conn = grpcx.Client.MustNewGrpcClientConn("demo") + client = protobuf.NewGreeterClient(conn) + ctx = grpcx.Ctx.NewOutgoing(gctx.New(), g.Map{ + "UserId": "1000", + "UserName": "john", + }) + ) + g.Log().Infof(ctx, `outgoing data: %v`, grpcx.Ctx.OutgoingMap(ctx).Map()) + res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"}) + if err != nil { + g.Log().Error(ctx, err) + return + } + g.Log().Debug(ctx, "Response:", res.Message) +} diff --git a/example/rpc/grpcx/ctx/controller/helloworld.go b/example/rpc/grpcx/ctx/controller/helloworld.go new file mode 100644 index 000000000..03a3240b8 --- /dev/null +++ b/example/rpc/grpcx/ctx/controller/helloworld.go @@ -0,0 +1,30 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package controller + +import ( + "context" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/ctx/protobuf" + "github.com/gogf/gf/v2/frame/g" +) + +type Controller struct { + protobuf.UnimplementedGreeterServer +} + +func Register(s *grpcx.GrpcServer) { + protobuf.RegisterGreeterServer(s.Server, &Controller{}) +} + +// SayHello implements helloworld.GreeterServer +func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) { + m := grpcx.Ctx.IncomingMap(ctx) + g.Log().Infof(ctx, `incoming data: %v`, m.Map()) + return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/example/rpc/grpcx/ctx/protobuf/helloworld.pb.go b/example/rpc/grpcx/ctx/protobuf/helloworld.pb.go new file mode 100644 index 000000000..8af3b213b --- /dev/null +++ b/example/rpc/grpcx/ctx/protobuf/helloworld.pb.go @@ -0,0 +1,217 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x22, 0x0a, 0x0c, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x45, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, + 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, + 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x67, 0x66, 0x2f, 0x67, 0x66, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protobuf.HelloRequest + (*HelloReply)(nil), // 1: protobuf.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: protobuf.Greeter.SayHello:input_type -> protobuf.HelloRequest + 1, // 1: protobuf.Greeter.SayHello:output_type -> protobuf.HelloReply + 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_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); 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_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/example/rpc/grpcx/ctx/protobuf/helloworld.proto b/example/rpc/grpcx/ctx/protobuf/helloworld.proto new file mode 100644 index 000000000..9f4f4864f --- /dev/null +++ b/example/rpc/grpcx/ctx/protobuf/helloworld.proto @@ -0,0 +1,24 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +syntax = "proto3"; + +package protobuf; + +option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/example/rpc/grpcx/ctx/protobuf/helloworld_grpc.pb.go b/example/rpc/grpcx/ctx/protobuf/helloworld_grpc.pb.go new file mode 100644 index 000000000..af29539f4 --- /dev/null +++ b/example/rpc/grpcx/ctx/protobuf/helloworld_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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 + +// GreeterClient is the client API for Greeter 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 GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/protobuf.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "protobuf.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/example/rpc/grpcx/ctx/server/config.yaml b/example/rpc/grpcx/ctx/server/config.yaml new file mode 100644 index 000000000..071b62623 --- /dev/null +++ b/example/rpc/grpcx/ctx/server/config.yaml @@ -0,0 +1,8 @@ +grpc: + name: "demo" + logPath: "./log" + logStdout: true + errorLogEnabled: true + accessLogEnabled: true + errorStack: true + diff --git a/example/rpc/grpcx/ctx/server/server.go b/example/rpc/grpcx/ctx/server/server.go new file mode 100644 index 000000000..83aa82af8 --- /dev/null +++ b/example/rpc/grpcx/ctx/server/server.go @@ -0,0 +1,18 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/ctx/controller" +) + +func main() { + s := grpcx.Server.New() + controller.Register(s) + s.Run() +} diff --git a/example/rpc/grpcx/rawgrpc/greeter_client/main.go b/example/rpc/grpcx/rawgrpc/client/client.go similarity index 83% rename from example/rpc/grpcx/rawgrpc/greeter_client/main.go rename to example/rpc/grpcx/rawgrpc/client/client.go index 8d54a160e..5a01ee751 100644 --- a/example/rpc/grpcx/rawgrpc/greeter_client/main.go +++ b/example/rpc/grpcx/rawgrpc/client/client.go @@ -7,9 +7,10 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" + "github.com/gogf/gf/contrib/registry/file/v2" "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/v2/os/gfile" - "github.com/gogf/gf/contrib/registry/etcd/v2" pb "github.com/gogf/gf/example/rpc/grpcx/rawgrpc/helloworld" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gsvc" @@ -17,7 +18,7 @@ import ( ) func main() { - gsvc.SetRegistry(etcd.New("127.0.0.1:2379")) + grpcx.Resolver.Register(file.New(gfile.Temp("gsvc"))) var ( ctx = gctx.GetInitCtx() @@ -25,7 +26,7 @@ func main() { ) // Set up a connection to the server. conn, err := grpc.Dial( - fmt.Sprintf(`%s`, service.GetKey()), + fmt.Sprintf(`%s://%s`, gsvc.Schema, service.GetKey()), grpcx.Balancer.WithRandom(), grpc.WithTransportCredentials(insecure.NewCredentials()), ) diff --git a/example/rpc/grpcx/rawgrpc/helloworld/helloworld.proto b/example/rpc/grpcx/rawgrpc/helloworld/helloworld.proto index 692ef9ded..a8eb37bdc 100644 --- a/example/rpc/grpcx/rawgrpc/helloworld/helloworld.proto +++ b/example/rpc/grpcx/rawgrpc/helloworld/helloworld.proto @@ -1,26 +1,13 @@ -// Copyright 2015 gRPC authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto syntax = "proto3"; -option go_package = "google.golang.org/grpc/examples/helloworld/helloworld"; -option java_multiple_files = true; -option java_package = "io.grpc.examples.helloworld"; -option java_outer_classname = "HelloWorldProto"; package helloworld; +option go_package = "github.com/gogf/gf/grpc/example/helloworld"; + + // The greeting service definition. service Greeter { // Sends a greeting diff --git a/example/rpc/grpcx/rawgrpc/greeter_server/main.go b/example/rpc/grpcx/rawgrpc/server/server.go similarity index 69% rename from example/rpc/grpcx/rawgrpc/greeter_server/main.go rename to example/rpc/grpcx/rawgrpc/server/server.go index 6a7511267..5ddf4991a 100644 --- a/example/rpc/grpcx/rawgrpc/greeter_server/main.go +++ b/example/rpc/grpcx/rawgrpc/server/server.go @@ -7,27 +7,27 @@ import ( "google.golang.org/grpc" - "github.com/gogf/gf/contrib/registry/etcd/v2" - pb "github.com/gogf/gf/example/rpc/grpcx/rawgrpc/helloworld" + "github.com/gogf/gf/contrib/registry/file/v2" + "github.com/gogf/gf/example/rpc/grpcx/rawgrpc/helloworld" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gipv4" "github.com/gogf/gf/v2/net/gsvc" "github.com/gogf/gf/v2/net/gtcp" "github.com/gogf/gf/v2/os/gctx" + "github.com/gogf/gf/v2/os/gfile" ) type GreetingServer struct { - pb.UnimplementedGreeterServer + helloworld.UnimplementedGreeterServer } // SayHello implements helloworld.GreeterServer -func (s *GreetingServer) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { - g.Log().Printf(ctx, "Received: %v", in.GetName()) - return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil +func (s *GreetingServer) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) { + return &helloworld.HelloReply{Message: "Hello " + in.GetName()}, nil } func main() { - gsvc.SetRegistry(etcd.New("127.0.0.1:2379")) + gsvc.SetRegistry(file.New(gfile.Temp("gsvc"))) var ( err error @@ -55,7 +55,7 @@ func main() { } s := grpc.NewServer() - pb.RegisterGreeterServer(s, &GreetingServer{}) + helloworld.RegisterGreeterServer(s, &GreetingServer{}) g.Log().Printf(ctx, "server listening at %v", listen.Addr()) if err = s.Serve(listen); err != nil { g.Log().Fatalf(ctx, "failed to serve: %v", err) diff --git a/example/rpc/grpcx/resolver/client/client.go b/example/rpc/grpcx/resolver/client/client.go new file mode 100644 index 000000000..ae2fefc4f --- /dev/null +++ b/example/rpc/grpcx/resolver/client/client.go @@ -0,0 +1,31 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/resolver/protobuf" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + + var ( + ctx = gctx.New() + conn = grpcx.Client.MustNewGrpcClientConn("demo") + client = protobuf.NewGreeterClient(conn) + ) + res, err := client.SayHello(ctx, &protobuf.HelloRequest{Name: "World"}) + if err != nil { + g.Log().Error(ctx, err) + return + } + g.Log().Debug(ctx, "Response:", res.Message) +} diff --git a/example/rpc/grpcx/resolver/controller/helloworld.go b/example/rpc/grpcx/resolver/controller/helloworld.go new file mode 100644 index 000000000..797a4580a --- /dev/null +++ b/example/rpc/grpcx/resolver/controller/helloworld.go @@ -0,0 +1,27 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package controller + +import ( + "context" + + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/resolver/protobuf" +) + +type Controller struct { + protobuf.UnimplementedGreeterServer +} + +func Register(s *grpcx.GrpcServer) { + protobuf.RegisterGreeterServer(s.Server, &Controller{}) +} + +// SayHello implements helloworld.GreeterServer +func (s *Controller) SayHello(ctx context.Context, in *protobuf.HelloRequest) (*protobuf.HelloReply, error) { + return &protobuf.HelloReply{Message: "Hello " + in.GetName()}, nil +} diff --git a/example/rpc/grpcx/resolver/protobuf/helloworld.pb.go b/example/rpc/grpcx/resolver/protobuf/helloworld.pb.go new file mode 100644 index 000000000..8af3b213b --- /dev/null +++ b/example/rpc/grpcx/resolver/protobuf/helloworld.pb.go @@ -0,0 +1,217 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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) +) + +// The request message containing the user's name. +type HelloRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *HelloRequest) Reset() { + *x = HelloRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloRequest) ProtoMessage() {} + +func (x *HelloRequest) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloRequest.ProtoReflect.Descriptor instead. +func (*HelloRequest) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{0} +} + +func (x *HelloRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// The response message containing the greetings +type HelloReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Message string `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *HelloReply) Reset() { + *x = HelloReply{} + if protoimpl.UnsafeEnabled { + mi := &file_helloworld_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HelloReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HelloReply) ProtoMessage() {} + +func (x *HelloReply) ProtoReflect() protoreflect.Message { + mi := &file_helloworld_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 HelloReply.ProtoReflect.Descriptor instead. +func (*HelloReply) Descriptor() ([]byte, []int) { + return file_helloworld_proto_rawDescGZIP(), []int{1} +} + +func (x *HelloReply) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +var File_helloworld_proto protoreflect.FileDescriptor + +var file_helloworld_proto_rawDesc = []byte{ + 0x0a, 0x10, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x22, 0x0a, 0x0c, + 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x26, 0x0a, 0x0a, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, + 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0x45, 0x0a, 0x07, 0x47, 0x72, 0x65, 0x65, + 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x08, 0x53, 0x61, 0x79, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x12, + 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, + 0x35, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, + 0x67, 0x66, 0x2f, 0x67, 0x66, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, + 0x6c, 0x65, 0x2f, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_helloworld_proto_rawDescOnce sync.Once + file_helloworld_proto_rawDescData = file_helloworld_proto_rawDesc +) + +func file_helloworld_proto_rawDescGZIP() []byte { + file_helloworld_proto_rawDescOnce.Do(func() { + file_helloworld_proto_rawDescData = protoimpl.X.CompressGZIP(file_helloworld_proto_rawDescData) + }) + return file_helloworld_proto_rawDescData +} + +var file_helloworld_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_helloworld_proto_goTypes = []interface{}{ + (*HelloRequest)(nil), // 0: protobuf.HelloRequest + (*HelloReply)(nil), // 1: protobuf.HelloReply +} +var file_helloworld_proto_depIdxs = []int32{ + 0, // 0: protobuf.Greeter.SayHello:input_type -> protobuf.HelloRequest + 1, // 1: protobuf.Greeter.SayHello:output_type -> protobuf.HelloReply + 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_helloworld_proto_init() } +func file_helloworld_proto_init() { + if File_helloworld_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_helloworld_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_helloworld_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HelloReply); 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_helloworld_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_helloworld_proto_goTypes, + DependencyIndexes: file_helloworld_proto_depIdxs, + MessageInfos: file_helloworld_proto_msgTypes, + }.Build() + File_helloworld_proto = out.File + file_helloworld_proto_rawDesc = nil + file_helloworld_proto_goTypes = nil + file_helloworld_proto_depIdxs = nil +} diff --git a/example/rpc/grpcx/resolver/protobuf/helloworld.proto b/example/rpc/grpcx/resolver/protobuf/helloworld.proto new file mode 100644 index 000000000..9f4f4864f --- /dev/null +++ b/example/rpc/grpcx/resolver/protobuf/helloworld.proto @@ -0,0 +1,24 @@ +// protoc --go_out=paths=source_relative:. --go-grpc_out=paths=source_relative:. *.proto + +syntax = "proto3"; + +package protobuf; + +option go_package = "github.com/gogf/gf/grpc/example/helloworld/protobuf"; + + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/example/rpc/grpcx/resolver/protobuf/helloworld_grpc.pb.go b/example/rpc/grpcx/resolver/protobuf/helloworld_grpc.pb.go new file mode 100644 index 000000000..af29539f4 --- /dev/null +++ b/example/rpc/grpcx/resolver/protobuf/helloworld_grpc.pb.go @@ -0,0 +1,107 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.2.0 +// - protoc v3.21.12 +// source: helloworld.proto + +package protobuf + +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 + +// GreeterClient is the client API for Greeter 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 GreeterClient interface { + // Sends a greeting + SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) +} + +type greeterClient struct { + cc grpc.ClientConnInterface +} + +func NewGreeterClient(cc grpc.ClientConnInterface) GreeterClient { + return &greeterClient{cc} +} + +func (c *greeterClient) SayHello(ctx context.Context, in *HelloRequest, opts ...grpc.CallOption) (*HelloReply, error) { + out := new(HelloReply) + err := c.cc.Invoke(ctx, "/protobuf.Greeter/SayHello", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// GreeterServer is the server API for Greeter service. +// All implementations must embed UnimplementedGreeterServer +// for forward compatibility +type GreeterServer interface { + // Sends a greeting + SayHello(context.Context, *HelloRequest) (*HelloReply, error) + mustEmbedUnimplementedGreeterServer() +} + +// UnimplementedGreeterServer must be embedded to have forward compatible implementations. +type UnimplementedGreeterServer struct { +} + +func (UnimplementedGreeterServer) SayHello(context.Context, *HelloRequest) (*HelloReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method SayHello not implemented") +} +func (UnimplementedGreeterServer) mustEmbedUnimplementedGreeterServer() {} + +// UnsafeGreeterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to GreeterServer will +// result in compilation errors. +type UnsafeGreeterServer interface { + mustEmbedUnimplementedGreeterServer() +} + +func RegisterGreeterServer(s grpc.ServiceRegistrar, srv GreeterServer) { + s.RegisterService(&Greeter_ServiceDesc, srv) +} + +func _Greeter_SayHello_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(HelloRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreeterServer).SayHello(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/protobuf.Greeter/SayHello", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreeterServer).SayHello(ctx, req.(*HelloRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// Greeter_ServiceDesc is the grpc.ServiceDesc for Greeter service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var Greeter_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "protobuf.Greeter", + HandlerType: (*GreeterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "SayHello", + Handler: _Greeter_SayHello_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "helloworld.proto", +} diff --git a/example/rpc/grpcx/resolver/server/config.yaml b/example/rpc/grpcx/resolver/server/config.yaml new file mode 100644 index 000000000..071b62623 --- /dev/null +++ b/example/rpc/grpcx/resolver/server/config.yaml @@ -0,0 +1,8 @@ +grpc: + name: "demo" + logPath: "./log" + logStdout: true + errorLogEnabled: true + accessLogEnabled: true + errorStack: true + diff --git a/example/rpc/grpcx/resolver/server/server.go b/example/rpc/grpcx/resolver/server/server.go new file mode 100644 index 000000000..7d8f1beb6 --- /dev/null +++ b/example/rpc/grpcx/resolver/server/server.go @@ -0,0 +1,21 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package main + +import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/contrib/rpc/grpcx/v2" + "github.com/gogf/gf/example/rpc/grpcx/resolver/controller" +) + +func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + + s := grpcx.Server.New() + controller.Register(s) + s.Run() +} diff --git a/example/trace/grpc_with_db/client/main.go b/example/trace/grpc_with_db/client/client.go similarity index 90% rename from example/trace/grpc_with_db/client/main.go rename to example/trace/grpc_with_db/client/client.go index 54ea8e168..cd8748fa7 100644 --- a/example/trace/grpc_with_db/client/main.go +++ b/example/trace/grpc_with_db/client/client.go @@ -1,9 +1,10 @@ package main import ( + "github.com/gogf/gf/contrib/registry/etcd/v2" "github.com/gogf/gf/contrib/rpc/grpcx/v2" "github.com/gogf/gf/contrib/trace/jaeger/v2" - "github.com/gogf/gf/example/trace/grpc_with_db/protocol/user" + "github.com/gogf/gf/example/trace/grpc_with_db/protobuf/user" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/gtrace" "github.com/gogf/gf/v2/os/gctx" @@ -15,6 +16,8 @@ const ( ) func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + var ctx = gctx.New() tp, err := jaeger.Init(ServiceName, JaegerUdpEndpoint) if err != nil { diff --git a/example/trace/grpc_with_db/client/config.yaml b/example/trace/grpc_with_db/client/config.yaml deleted file mode 100644 index 28108a23a..000000000 --- a/example/trace/grpc_with_db/client/config.yaml +++ /dev/null @@ -1,6 +0,0 @@ - -registry: - endpoints: ["127.0.0.1:2379"] - - - diff --git a/example/trace/grpc_with_db/protobuf/user/user.pb.go b/example/trace/grpc_with_db/protobuf/user/user.pb.go new file mode 100644 index 000000000..5b24ba189 --- /dev/null +++ b/example/trace/grpc_with_db/protobuf/user/user.pb.go @@ -0,0 +1,469 @@ +// protoc --gofast_out=plugins=grpc:. \ +// protocol/user/*.proto \ +// -I/Users/john/Workspace/Go/GOPATH/src + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.12 +// source: user.proto + +package user + +import ( + reflect "reflect" + sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" +) + +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 InsertReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty" v:"required#Please input user name."` // v: required#Please input user name. +} + +func (x *InsertReq) Reset() { + *x = InsertReq{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InsertReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InsertReq) ProtoMessage() {} + +func (x *InsertReq) ProtoReflect() protoreflect.Message { + mi := &file_user_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 InsertReq.ProtoReflect.Descriptor instead. +func (*InsertReq) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{0} +} + +func (x *InsertReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type InsertRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"` +} + +func (x *InsertRes) Reset() { + *x = InsertRes{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InsertRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InsertRes) ProtoMessage() {} + +func (x *InsertRes) ProtoReflect() protoreflect.Message { + mi := &file_user_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 InsertRes.ProtoReflect.Descriptor instead. +func (*InsertRes) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{1} +} + +func (x *InsertRes) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type QueryReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty" v:"min:1#User id is required for querying."` // v: min:1#User id is required for querying. +} + +func (x *QueryReq) Reset() { + *x = QueryReq{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryReq) ProtoMessage() {} + +func (x *QueryReq) ProtoReflect() protoreflect.Message { + mi := &file_user_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 QueryReq.ProtoReflect.Descriptor instead. +func (*QueryReq) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{2} +} + +func (x *QueryReq) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type QueryRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` +} + +func (x *QueryRes) Reset() { + *x = QueryRes{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryRes) ProtoMessage() {} + +func (x *QueryRes) ProtoReflect() protoreflect.Message { + mi := &file_user_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 QueryRes.ProtoReflect.Descriptor instead. +func (*QueryRes) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{3} +} + +func (x *QueryRes) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *QueryRes) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type DeleteReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty" v:"min:1#User id is required for deleting."` // v:min:1#User id is required for deleting. +} + +func (x *DeleteReq) Reset() { + *x = DeleteReq{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteReq) ProtoMessage() {} + +func (x *DeleteReq) ProtoReflect() protoreflect.Message { + mi := &file_user_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 DeleteReq.ProtoReflect.Descriptor instead. +func (*DeleteReq) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{4} +} + +func (x *DeleteReq) GetId() int32 { + if x != nil { + return x.Id + } + return 0 +} + +type DeleteRes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *DeleteRes) Reset() { + *x = DeleteRes{} + if protoimpl.UnsafeEnabled { + mi := &file_user_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRes) ProtoMessage() {} + +func (x *DeleteRes) ProtoReflect() protoreflect.Message { + mi := &file_user_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 DeleteRes.ProtoReflect.Descriptor instead. +func (*DeleteRes) Descriptor() ([]byte, []int) { + return file_user_proto_rawDescGZIP(), []int{5} +} + +var File_user_proto protoreflect.FileDescriptor + +var file_user_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x75, 0x73, + 0x65, 0x72, 0x22, 0x1f, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x12, + 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, + 0x61, 0x6d, 0x65, 0x22, 0x1b, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, + 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, + 0x22, 0x1a, 0x0a, 0x08, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, + 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x22, 0x2e, 0x0a, 0x08, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x1b, 0x0a, 0x09, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x49, 0x64, 0x22, 0x0b, 0x0a, 0x09, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x32, 0x8d, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x2c, 0x0a, 0x06, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x12, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, + 0x2e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x2e, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x29, 0x0a, + 0x05, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x0e, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x1a, 0x0e, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x22, 0x00, 0x12, 0x2c, 0x0a, 0x06, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x12, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x22, 0x00, 0x42, 0x0f, 0x5a, 0x0d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_user_proto_rawDescOnce sync.Once + file_user_proto_rawDescData = file_user_proto_rawDesc +) + +func file_user_proto_rawDescGZIP() []byte { + file_user_proto_rawDescOnce.Do(func() { + file_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_user_proto_rawDescData) + }) + return file_user_proto_rawDescData +} + +var file_user_proto_msgTypes = make([]protoimpl.MessageInfo, 6) +var file_user_proto_goTypes = []interface{}{ + (*InsertReq)(nil), // 0: user.InsertReq + (*InsertRes)(nil), // 1: user.InsertRes + (*QueryReq)(nil), // 2: user.QueryReq + (*QueryRes)(nil), // 3: user.QueryRes + (*DeleteReq)(nil), // 4: user.DeleteReq + (*DeleteRes)(nil), // 5: user.DeleteRes +} +var file_user_proto_depIdxs = []int32{ + 0, // 0: user.User.Insert:input_type -> user.InsertReq + 2, // 1: user.User.Query:input_type -> user.QueryReq + 4, // 2: user.User.Delete:input_type -> user.DeleteReq + 1, // 3: user.User.Insert:output_type -> user.InsertRes + 3, // 4: user.User.Query:output_type -> user.QueryRes + 5, // 5: user.User.Delete:output_type -> user.DeleteRes + 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_user_proto_init() } +func file_user_proto_init() { + if File_user_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InsertReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InsertRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryRes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_user_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DeleteRes); 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_user_proto_rawDesc, + NumEnums: 0, + NumMessages: 6, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_user_proto_goTypes, + DependencyIndexes: file_user_proto_depIdxs, + MessageInfos: file_user_proto_msgTypes, + }.Build() + File_user_proto = out.File + file_user_proto_rawDesc = nil + file_user_proto_goTypes = nil + file_user_proto_depIdxs = nil +} diff --git a/example/trace/grpc_with_db/protobuf/user/user.proto b/example/trace/grpc_with_db/protobuf/user/user.proto index 1bcc8270d..bc9ad4dd4 100644 --- a/example/trace/grpc_with_db/protobuf/user/user.proto +++ b/example/trace/grpc_with_db/protobuf/user/user.proto @@ -7,8 +7,6 @@ package user; option go_package = "protobuf/user"; -import "github.com/gogo/protobuf/gogoproto/gogo.proto"; - // User service for tracing demo. service User { rpc Insert(InsertReq) returns (InsertRes) {} @@ -17,24 +15,21 @@ service User { } message InsertReq { - string Name = 1 [(gogoproto.moretags) = 'v:"required#Please input user name."']; + string Name = 1; // v: required#Please input user name. } - message InsertRes { int32 Id = 1; } message QueryReq { - int32 Id = 1 [(gogoproto.moretags) = 'v:"min:1#User id is required for querying."']; + int32 Id = 1; // v: min:1#User id is required for querying. } - message QueryRes { int32 Id = 1; string Name = 2; } message DeleteReq { - int32 Id = 1 [(gogoproto.moretags) = 'v:"min:1#User id is required for deleting."']; + int32 Id = 1; // v:min:1#User id is required for deleting. } - message DeleteRes {} \ No newline at end of file diff --git a/example/trace/grpc_with_db/protobuf/user/user_grpc.pb.go b/example/trace/grpc_with_db/protobuf/user/user_grpc.pb.go new file mode 100644 index 000000000..3bdd9b34e --- /dev/null +++ b/example/trace/grpc_with_db/protobuf/user/user_grpc.pb.go @@ -0,0 +1,188 @@ +// protoc --gofast_out=plugins=grpc:. \ +// protocol/user/*.proto \ +// -I/Users/john/Workspace/Go/GOPATH/src + +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.3.0 +// - protoc v3.21.12 +// source: user.proto + +package user + +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 + +const ( + User_Insert_FullMethodName = "/user.User/Insert" + User_Query_FullMethodName = "/user.User/Query" + User_Delete_FullMethodName = "/user.User/Delete" +) + +// UserClient is the client API for User 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 UserClient interface { + Insert(ctx context.Context, in *InsertReq, opts ...grpc.CallOption) (*InsertRes, error) + Query(ctx context.Context, in *QueryReq, opts ...grpc.CallOption) (*QueryRes, error) + Delete(ctx context.Context, in *DeleteReq, opts ...grpc.CallOption) (*DeleteRes, error) +} + +type userClient struct { + cc grpc.ClientConnInterface +} + +func NewUserClient(cc grpc.ClientConnInterface) UserClient { + return &userClient{cc} +} + +func (c *userClient) Insert(ctx context.Context, in *InsertReq, opts ...grpc.CallOption) (*InsertRes, error) { + out := new(InsertRes) + err := c.cc.Invoke(ctx, User_Insert_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userClient) Query(ctx context.Context, in *QueryReq, opts ...grpc.CallOption) (*QueryRes, error) { + out := new(QueryRes) + err := c.cc.Invoke(ctx, User_Query_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *userClient) Delete(ctx context.Context, in *DeleteReq, opts ...grpc.CallOption) (*DeleteRes, error) { + out := new(DeleteRes) + err := c.cc.Invoke(ctx, User_Delete_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// UserServer is the server API for User service. +// All implementations must embed UnimplementedUserServer +// for forward compatibility +type UserServer interface { + Insert(context.Context, *InsertReq) (*InsertRes, error) + Query(context.Context, *QueryReq) (*QueryRes, error) + Delete(context.Context, *DeleteReq) (*DeleteRes, error) + mustEmbedUnimplementedUserServer() +} + +// UnimplementedUserServer must be embedded to have forward compatible implementations. +type UnimplementedUserServer struct { +} + +func (UnimplementedUserServer) Insert(context.Context, *InsertReq) (*InsertRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method Insert not implemented") +} +func (UnimplementedUserServer) Query(context.Context, *QueryReq) (*QueryRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") +} +func (UnimplementedUserServer) Delete(context.Context, *DeleteReq) (*DeleteRes, error) { + return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") +} +func (UnimplementedUserServer) mustEmbedUnimplementedUserServer() {} + +// UnsafeUserServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to UserServer will +// result in compilation errors. +type UnsafeUserServer interface { + mustEmbedUnimplementedUserServer() +} + +func RegisterUserServer(s grpc.ServiceRegistrar, srv UserServer) { + s.RegisterService(&User_ServiceDesc, srv) +} + +func _User_Insert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InsertReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Insert(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: User_Insert_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Insert(ctx, req.(*InsertReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _User_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QueryReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Query(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: User_Query_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Query(ctx, req.(*QueryReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _User_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(UserServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: User_Delete_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(UserServer).Delete(ctx, req.(*DeleteReq)) + } + return interceptor(ctx, in, info, handler) +} + +// User_ServiceDesc is the grpc.ServiceDesc for User service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var User_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "user.User", + HandlerType: (*UserServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Insert", + Handler: _User_Insert_Handler, + }, + { + MethodName: "Query", + Handler: _User_Query_Handler, + }, + { + MethodName: "Delete", + Handler: _User_Delete_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "user.proto", +} diff --git a/example/trace/grpc_with_db/protocol/user/user.pb.go b/example/trace/grpc_with_db/protocol/user/user.pb.go deleted file mode 100644 index bd0e0ea2f..000000000 --- a/example/trace/grpc_with_db/protocol/user/user.pb.go +++ /dev/null @@ -1,1335 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: protocol/user/user.proto - -package user - -import ( - context "context" - fmt "fmt" - _ "github.com/gogo/protobuf/gogoproto" - proto "github.com/golang/protobuf/proto" - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package - -type InsertReq struct { - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty" v:"required#Please input user name."` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *InsertReq) Reset() { *m = InsertReq{} } -func (m *InsertReq) String() string { return proto.CompactTextString(m) } -func (*InsertReq) ProtoMessage() {} -func (*InsertReq) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{0} -} -func (m *InsertReq) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InsertReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InsertReq.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *InsertReq) XXX_Merge(src proto.Message) { - xxx_messageInfo_InsertReq.Merge(m, src) -} -func (m *InsertReq) XXX_Size() int { - return m.Size() -} -func (m *InsertReq) XXX_DiscardUnknown() { - xxx_messageInfo_InsertReq.DiscardUnknown(m) -} - -var xxx_messageInfo_InsertReq proto.InternalMessageInfo - -func (m *InsertReq) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -type InsertRes struct { - Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *InsertRes) Reset() { *m = InsertRes{} } -func (m *InsertRes) String() string { return proto.CompactTextString(m) } -func (*InsertRes) ProtoMessage() {} -func (*InsertRes) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{1} -} -func (m *InsertRes) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *InsertRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_InsertRes.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *InsertRes) XXX_Merge(src proto.Message) { - xxx_messageInfo_InsertRes.Merge(m, src) -} -func (m *InsertRes) XXX_Size() int { - return m.Size() -} -func (m *InsertRes) XXX_DiscardUnknown() { - xxx_messageInfo_InsertRes.DiscardUnknown(m) -} - -var xxx_messageInfo_InsertRes proto.InternalMessageInfo - -func (m *InsertRes) GetId() int32 { - if m != nil { - return m.Id - } - return 0 -} - -type QueryReq struct { - Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty" v:"min:1#User id is required for querying."` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *QueryReq) Reset() { *m = QueryReq{} } -func (m *QueryReq) String() string { return proto.CompactTextString(m) } -func (*QueryReq) ProtoMessage() {} -func (*QueryReq) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{2} -} -func (m *QueryReq) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryReq.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryReq) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryReq.Merge(m, src) -} -func (m *QueryReq) XXX_Size() int { - return m.Size() -} -func (m *QueryReq) XXX_DiscardUnknown() { - xxx_messageInfo_QueryReq.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryReq proto.InternalMessageInfo - -func (m *QueryReq) GetId() int32 { - if m != nil { - return m.Id - } - return 0 -} - -type QueryRes struct { - Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty"` - Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *QueryRes) Reset() { *m = QueryRes{} } -func (m *QueryRes) String() string { return proto.CompactTextString(m) } -func (*QueryRes) ProtoMessage() {} -func (*QueryRes) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{3} -} -func (m *QueryRes) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *QueryRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_QueryRes.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *QueryRes) XXX_Merge(src proto.Message) { - xxx_messageInfo_QueryRes.Merge(m, src) -} -func (m *QueryRes) XXX_Size() int { - return m.Size() -} -func (m *QueryRes) XXX_DiscardUnknown() { - xxx_messageInfo_QueryRes.DiscardUnknown(m) -} - -var xxx_messageInfo_QueryRes proto.InternalMessageInfo - -func (m *QueryRes) GetId() int32 { - if m != nil { - return m.Id - } - return 0 -} - -func (m *QueryRes) GetName() string { - if m != nil { - return m.Name - } - return "" -} - -type DeleteReq struct { - Id int32 `protobuf:"varint,1,opt,name=Id,proto3" json:"Id,omitempty" v:"min:1#User id is required for deleting."` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteReq) Reset() { *m = DeleteReq{} } -func (m *DeleteReq) String() string { return proto.CompactTextString(m) } -func (*DeleteReq) ProtoMessage() {} -func (*DeleteReq) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{4} -} -func (m *DeleteReq) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *DeleteReq) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_DeleteReq.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *DeleteReq) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteReq.Merge(m, src) -} -func (m *DeleteReq) XXX_Size() int { - return m.Size() -} -func (m *DeleteReq) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteReq.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteReq proto.InternalMessageInfo - -func (m *DeleteReq) GetId() int32 { - if m != nil { - return m.Id - } - return 0 -} - -type DeleteRes struct { - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` -} - -func (m *DeleteRes) Reset() { *m = DeleteRes{} } -func (m *DeleteRes) String() string { return proto.CompactTextString(m) } -func (*DeleteRes) ProtoMessage() {} -func (*DeleteRes) Descriptor() ([]byte, []int) { - return fileDescriptor_2a1d51345ecfe4e5, []int{5} -} -func (m *DeleteRes) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *DeleteRes) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_DeleteRes.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *DeleteRes) XXX_Merge(src proto.Message) { - xxx_messageInfo_DeleteRes.Merge(m, src) -} -func (m *DeleteRes) XXX_Size() int { - return m.Size() -} -func (m *DeleteRes) XXX_DiscardUnknown() { - xxx_messageInfo_DeleteRes.DiscardUnknown(m) -} - -var xxx_messageInfo_DeleteRes proto.InternalMessageInfo - -func init() { - proto.RegisterType((*InsertReq)(nil), "user.InsertReq") - proto.RegisterType((*InsertRes)(nil), "user.InsertRes") - proto.RegisterType((*QueryReq)(nil), "user.QueryReq") - proto.RegisterType((*QueryRes)(nil), "user.QueryRes") - proto.RegisterType((*DeleteReq)(nil), "user.DeleteReq") - proto.RegisterType((*DeleteRes)(nil), "user.DeleteRes") -} - -func init() { proto.RegisterFile("protocol/user/user.proto", fileDescriptor_2a1d51345ecfe4e5) } - -var fileDescriptor_2a1d51345ecfe4e5 = []byte{ - // 345 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0xc1, 0x4a, 0xc3, 0x40, - 0x10, 0x6d, 0x4a, 0x5b, 0xec, 0x8a, 0x15, 0xf6, 0x54, 0x22, 0xa4, 0xcb, 0xd6, 0x43, 0xc5, 0x9a, - 0xa0, 0xde, 0x8a, 0x20, 0x14, 0x2f, 0x41, 0x11, 0x2d, 0x78, 0xf1, 0xd6, 0x36, 0xd3, 0xb8, 0xd0, - 0x64, 0xdb, 0xdd, 0xa4, 0xe0, 0x47, 0x78, 0xf7, 0x93, 0x3c, 0xfa, 0x05, 0x45, 0xea, 0x1f, 0xf4, - 0x0b, 0x64, 0x27, 0x6d, 0x82, 0xf5, 0xe6, 0x25, 0xcc, 0x9b, 0x99, 0xf7, 0x5e, 0xde, 0x24, 0xa4, - 0x39, 0x53, 0x32, 0x91, 0x63, 0x39, 0xf5, 0x52, 0x0d, 0x0a, 0x1f, 0x2e, 0xb6, 0x68, 0xc5, 0xd4, - 0xf6, 0x59, 0x28, 0x92, 0x97, 0x74, 0xe4, 0x8e, 0x65, 0xe4, 0x85, 0x32, 0x94, 0x1e, 0x0e, 0x47, - 0xe9, 0x04, 0x11, 0x02, 0xac, 0x32, 0x12, 0xf7, 0x49, 0xdd, 0x8f, 0x35, 0xa8, 0x64, 0x00, 0x73, - 0x7a, 0x45, 0x2a, 0xf7, 0xc3, 0x08, 0x9a, 0x16, 0xb3, 0x3a, 0xf5, 0x7e, 0x67, 0xbd, 0x6c, 0x1d, - 0x2f, 0x7a, 0x5c, 0xc1, 0x3c, 0x15, 0x0a, 0x82, 0xf6, 0xc3, 0x14, 0x86, 0x1a, 0x98, 0x88, 0x67, - 0x69, 0xc2, 0x8c, 0x19, 0x8b, 0x87, 0x11, 0xb8, 0x7c, 0x80, 0x2c, 0x7e, 0x54, 0x48, 0x69, 0xda, - 0x20, 0x65, 0x3f, 0x40, 0xa1, 0xea, 0xa0, 0xec, 0x07, 0xfc, 0x96, 0xec, 0x3d, 0xa6, 0xa0, 0x5e, - 0x8d, 0xcd, 0x75, 0x31, 0xeb, 0x7b, 0xeb, 0x65, 0xeb, 0x74, 0xd1, 0xe3, 0x91, 0x88, 0x7b, 0xe7, - 0xed, 0x27, 0x23, 0x2a, 0x02, 0x26, 0x34, 0xdb, 0xba, 0xb2, 0x89, 0x54, 0x6c, 0x6e, 0xa8, 0x22, - 0x0e, 0x5d, 0x8e, 0x62, 0x6e, 0x2e, 0xf6, 0xc7, 0x88, 0xd2, 0x4d, 0x86, 0xb2, 0xc9, 0xb0, 0x79, - 0xb3, 0x3b, 0x52, 0xbf, 0x81, 0x29, 0x24, 0xf0, 0x3f, 0xf7, 0xc0, 0x70, 0x0b, 0xf7, 0xfd, 0x42, - 0x4d, 0x5f, 0xbc, 0x59, 0xa4, 0x62, 0x78, 0xb4, 0x4b, 0x6a, 0x59, 0x7a, 0x7a, 0xe8, 0xe2, 0x47, - 0xc9, 0xcf, 0x6a, 0xef, 0x34, 0x34, 0x2f, 0xd1, 0x13, 0x52, 0xc5, 0x04, 0xb4, 0x91, 0xcd, 0xb6, - 0xb7, 0xb1, 0x7f, 0x63, 0xb3, 0xda, 0x25, 0xb5, 0xcc, 0x6e, 0x2b, 0x9c, 0x47, 0xb1, 0x77, 0x1a, - 0x9a, 0x97, 0xfa, 0xad, 0x8f, 0x95, 0x63, 0x7d, 0xae, 0x1c, 0xeb, 0x6b, 0xe5, 0x58, 0xef, 0xdf, - 0x4e, 0xe9, 0xf9, 0x20, 0xff, 0x01, 0xcc, 0xf2, 0xa8, 0x86, 0xf0, 0xf2, 0x27, 0x00, 0x00, 0xff, - 0xff, 0xb9, 0xf8, 0x21, 0xb8, 0x48, 0x02, 0x00, 0x00, -} - -// Reference imports to suppress errors if they are not otherwise used. -var _ context.Context -var _ grpc.ClientConn - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -const _ = grpc.SupportPackageIsVersion4 - -// UserClient is the client API for User service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. -type UserClient interface { - Insert(ctx context.Context, in *InsertReq, opts ...grpc.CallOption) (*InsertRes, error) - Query(ctx context.Context, in *QueryReq, opts ...grpc.CallOption) (*QueryRes, error) - Delete(ctx context.Context, in *DeleteReq, opts ...grpc.CallOption) (*DeleteRes, error) -} - -type userClient struct { - cc *grpc.ClientConn -} - -func NewUserClient(cc *grpc.ClientConn) UserClient { - return &userClient{cc} -} - -func (c *userClient) Insert(ctx context.Context, in *InsertReq, opts ...grpc.CallOption) (*InsertRes, error) { - out := new(InsertRes) - err := c.cc.Invoke(ctx, "/user.User/Insert", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *userClient) Query(ctx context.Context, in *QueryReq, opts ...grpc.CallOption) (*QueryRes, error) { - out := new(QueryRes) - err := c.cc.Invoke(ctx, "/user.User/Query", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *userClient) Delete(ctx context.Context, in *DeleteReq, opts ...grpc.CallOption) (*DeleteRes, error) { - out := new(DeleteRes) - err := c.cc.Invoke(ctx, "/user.User/Delete", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - -// UserServer is the server API for User service. -type UserServer interface { - Insert(context.Context, *InsertReq) (*InsertRes, error) - Query(context.Context, *QueryReq) (*QueryRes, error) - Delete(context.Context, *DeleteReq) (*DeleteRes, error) -} - -// UnimplementedUserServer can be embedded to have forward compatible implementations. -type UnimplementedUserServer struct { -} - -func (*UnimplementedUserServer) Insert(ctx context.Context, req *InsertReq) (*InsertRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Insert not implemented") -} -func (*UnimplementedUserServer) Query(ctx context.Context, req *QueryReq) (*QueryRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Query not implemented") -} -func (*UnimplementedUserServer) Delete(ctx context.Context, req *DeleteReq) (*DeleteRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") -} - -func RegisterUserServer(s *grpc.Server, srv UserServer) { - s.RegisterService(&_User_serviceDesc, srv) -} - -func _User_Insert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(InsertReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UserServer).Insert(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/user.User/Insert", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UserServer).Insert(ctx, req.(*InsertReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _User_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(QueryReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UserServer).Query(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/user.User/Query", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UserServer).Query(ctx, req.(*QueryReq)) - } - return interceptor(ctx, in, info, handler) -} - -func _User_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(DeleteReq) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(UserServer).Delete(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/user.User/Delete", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(UserServer).Delete(ctx, req.(*DeleteReq)) - } - return interceptor(ctx, in, info, handler) -} - -var _User_serviceDesc = grpc.ServiceDesc{ - ServiceName: "user.User", - HandlerType: (*UserServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "Insert", - Handler: _User_Insert_Handler, - }, - { - MethodName: "Query", - Handler: _User_Query_Handler, - }, - { - MethodName: "Delete", - Handler: _User_Delete_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "protocol/user/user.proto", -} - -func (m *InsertReq) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *InsertReq) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InsertReq) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if len(m.Name) > 0 { - i -= len(m.Name) - copy(dAtA[i:], m.Name) - i = encodeVarintUser(dAtA, i, uint64(len(m.Name))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *InsertRes) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *InsertRes) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *InsertRes) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if m.Id != 0 { - i = encodeVarintUser(dAtA, i, uint64(m.Id)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *QueryReq) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryReq) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryReq) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if m.Id != 0 { - i = encodeVarintUser(dAtA, i, uint64(m.Id)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *QueryRes) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *QueryRes) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *QueryRes) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if len(m.Name) > 0 { - i -= len(m.Name) - copy(dAtA[i:], m.Name) - i = encodeVarintUser(dAtA, i, uint64(len(m.Name))) - i-- - dAtA[i] = 0x12 - } - if m.Id != 0 { - i = encodeVarintUser(dAtA, i, uint64(m.Id)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *DeleteReq) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *DeleteReq) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *DeleteReq) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - if m.Id != 0 { - i = encodeVarintUser(dAtA, i, uint64(m.Id)) - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - -func (m *DeleteRes) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *DeleteRes) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *DeleteRes) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.XXX_unrecognized != nil { - i -= len(m.XXX_unrecognized) - copy(dAtA[i:], m.XXX_unrecognized) - } - return len(dAtA) - i, nil -} - -func encodeVarintUser(dAtA []byte, offset int, v uint64) int { - offset -= sovUser(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *InsertReq) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sovUser(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *InsertRes) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != 0 { - n += 1 + sovUser(uint64(m.Id)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *QueryReq) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != 0 { - n += 1 + sovUser(uint64(m.Id)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *QueryRes) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != 0 { - n += 1 + sovUser(uint64(m.Id)) - } - l = len(m.Name) - if l > 0 { - n += 1 + l + sovUser(uint64(l)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *DeleteReq) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Id != 0 { - n += 1 + sovUser(uint64(m.Id)) - } - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func (m *DeleteRes) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.XXX_unrecognized != nil { - n += len(m.XXX_unrecognized) - } - return n -} - -func sovUser(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozUser(x uint64) (n int) { - return sovUser(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *InsertReq) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: InsertReq: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InsertReq: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthUser - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthUser - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *InsertRes) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: InsertRes: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: InsertRes: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryReq) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryReq: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryReq: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *QueryRes) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: QueryRes: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: QueryRes: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthUser - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthUser - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Name = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *DeleteReq) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: DeleteReq: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteReq: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) - } - m.Id = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Id |= int32(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *DeleteRes) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowUser - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: DeleteRes: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: DeleteRes: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - default: - iNdEx = preIndex - skippy, err := skipUser(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthUser - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...) - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipUser(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowUser - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowUser - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowUser - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthUser - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupUser - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthUser - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthUser = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowUser = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupUser = fmt.Errorf("proto: unexpected end of group") -) diff --git a/example/trace/grpc_with_db/server/main.go b/example/trace/grpc_with_db/server/server.go similarity index 72% rename from example/trace/grpc_with_db/server/main.go rename to example/trace/grpc_with_db/server/server.go index a400c9484..4ea7e1a57 100644 --- a/example/trace/grpc_with_db/server/main.go +++ b/example/trace/grpc_with_db/server/server.go @@ -3,6 +3,8 @@ package main import ( _ "github.com/gogf/gf/contrib/drivers/mysql/v2" _ "github.com/gogf/gf/contrib/nosql/redis/v2" + "github.com/gogf/gf/contrib/registry/etcd/v2" + "github.com/gogf/gf/example/trace/grpc_with_db/protobuf/user" "context" "fmt" @@ -10,14 +12,15 @@ import ( "github.com/gogf/gf/contrib/rpc/grpcx/v2" "github.com/gogf/gf/contrib/trace/jaeger/v2" - "github.com/gogf/gf/example/trace/grpc_with_db/protocol/user" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcache" "github.com/gogf/gf/v2/os/gctx" ) -type server struct{} +type Controller struct { + user.UnimplementedUserServer +} const ( ServiceName = "grpc-server-with-db" @@ -25,6 +28,8 @@ const ( ) func main() { + grpcx.Resolver.Register(etcd.New("127.0.0.1:2379")) + var ctx = gctx.New() tp, err := jaeger.Init(ServiceName, JaegerUdpEndpoint) if err != nil { @@ -36,12 +41,12 @@ func main() { g.DB().GetCache().SetAdapter(gcache.NewAdapterRedis(g.Redis())) s := grpcx.Server.New() - user.RegisterUserServer(s.Server, &server{}) + user.RegisterUserServer(s.Server, &Controller{}) s.Run() } // Insert is a route handler for inserting user info into database. -func (s *server) Insert(ctx context.Context, req *user.InsertReq) (res *user.InsertRes, err error) { +func (s *Controller) Insert(ctx context.Context, req *user.InsertReq) (res *user.InsertRes, err error) { result, err := g.Model("user").Ctx(ctx).Insert(g.Map{ "name": req.Name, }) @@ -57,7 +62,7 @@ func (s *server) Insert(ctx context.Context, req *user.InsertReq) (res *user.Ins // Query is a route handler for querying user info. It firstly retrieves the info from redis, // if there's nothing in the redis, it then does db select. -func (s *server) Query(ctx context.Context, req *user.QueryReq) (res *user.QueryRes, err error) { +func (s *Controller) Query(ctx context.Context, req *user.QueryReq) (res *user.QueryRes, err error) { err = g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{ Duration: 5 * time.Second, Name: s.userCacheKey(req.Id), @@ -70,7 +75,7 @@ func (s *server) Query(ctx context.Context, req *user.QueryReq) (res *user.Query } // Delete is a route handler for deleting specified user info. -func (s *server) Delete(ctx context.Context, req *user.DeleteReq) (res *user.DeleteRes, err error) { +func (s *Controller) Delete(ctx context.Context, req *user.DeleteReq) (res *user.DeleteRes, err error) { err = g.Model("user").Ctx(ctx).Cache(gdb.CacheOption{ Duration: -1, Name: s.userCacheKey(req.Id), @@ -79,6 +84,6 @@ func (s *server) Delete(ctx context.Context, req *user.DeleteReq) (res *user.Del return } -func (s *server) userCacheKey(id int32) string { +func (s *Controller) userCacheKey(id int32) string { return fmt.Sprintf(`userInfo:%d`, id) } diff --git a/example/trace/http/client/main.go b/example/trace/http/client/client.go similarity index 100% rename from example/trace/http/client/main.go rename to example/trace/http/client/client.go diff --git a/example/trace/http/server/main.go b/example/trace/http/server/server.go similarity index 100% rename from example/trace/http/server/main.go rename to example/trace/http/server/server.go diff --git a/example/trace/http_with_db/client/main.go b/example/trace/http_with_db/client/client.go similarity index 100% rename from example/trace/http_with_db/client/main.go rename to example/trace/http_with_db/client/client.go diff --git a/example/trace/http_with_db/server/main.go b/example/trace/http_with_db/server/server.go similarity index 100% rename from example/trace/http_with_db/server/main.go rename to example/trace/http_with_db/server/server.go diff --git a/version.go b/version.go index 13ced56fc..62e2267bb 100644 --- a/version.go +++ b/version.go @@ -2,5 +2,5 @@ package gf const ( // VERSION is the current GoFrame version. - VERSION = "v2.3.3" + VERSION = "v2.4.0-beta" )