From 7b41acf2416aa367a188431230391166ce39f34e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=85=E5=AD=90?= Date: Thu, 17 Jun 2021 17:57:23 +0800 Subject: [PATCH] add examples/errors (#1077) * addd examples/errors --- examples/errors/api/error_reason.pb.go | 136 ++++++++++++++++++ examples/errors/api/error_reason.proto | 17 +++ examples/errors/api/error_reason_errors.pb.go | 30 ++++ examples/errors/api/errors.proto | 18 +++ examples/errors/client/main.go | 62 ++++++++ examples/errors/server/main.go | 65 +++++++++ 6 files changed, 328 insertions(+) create mode 100644 examples/errors/api/error_reason.pb.go create mode 100644 examples/errors/api/error_reason.proto create mode 100644 examples/errors/api/error_reason_errors.pb.go create mode 100644 examples/errors/api/errors.proto create mode 100644 examples/errors/client/main.go create mode 100644 examples/errors/server/main.go diff --git a/examples/errors/api/error_reason.pb.go b/examples/errors/api/error_reason.pb.go new file mode 100644 index 000000000..1f850e471 --- /dev/null +++ b/examples/errors/api/error_reason.pb.go @@ -0,0 +1,136 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.17.1 +// source: error_reason.proto + +package api + +import ( + _ "github.com/go-kratos/kratos/v2/errors" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type ErrorReason int32 + +const ( + ErrorReason_USER_NOT_FOUND ErrorReason = 0 + ErrorReason_CONTENT_MISSING ErrorReason = 1 +) + +// Enum value maps for ErrorReason. +var ( + ErrorReason_name = map[int32]string{ + 0: "USER_NOT_FOUND", + 1: "CONTENT_MISSING", + } + ErrorReason_value = map[string]int32{ + "USER_NOT_FOUND": 0, + "CONTENT_MISSING": 1, + } +) + +func (x ErrorReason) Enum() *ErrorReason { + p := new(ErrorReason) + *p = x + return p +} + +func (x ErrorReason) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ErrorReason) Descriptor() protoreflect.EnumDescriptor { + return file_error_reason_proto_enumTypes[0].Descriptor() +} + +func (ErrorReason) Type() protoreflect.EnumType { + return &file_error_reason_proto_enumTypes[0] +} + +func (x ErrorReason) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ErrorReason.Descriptor instead. +func (ErrorReason) EnumDescriptor() ([]byte, []int) { + return file_error_reason_proto_rawDescGZIP(), []int{0} +} + +var File_error_reason_proto protoreflect.FileDescriptor + +var file_error_reason_proto_rawDesc = []byte{ + 0x0a, 0x12, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x1a, 0x0c, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2a, 0x48, 0x0a, 0x0b, 0x45, 0x72, + 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x0e, 0x55, 0x53, 0x45, + 0x52, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x46, 0x4f, 0x55, 0x4e, 0x44, 0x10, 0x00, 0x1a, 0x04, 0xa8, + 0x45, 0x94, 0x03, 0x12, 0x19, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x45, 0x4e, 0x54, 0x5f, 0x4d, + 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x1a, 0x04, 0xa8, 0x45, 0x90, 0x03, 0x1a, 0x04, + 0xa0, 0x45, 0xf4, 0x03, 0x42, 0x57, 0x0a, 0x0e, 0x62, 0x6c, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x2e, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x50, 0x01, 0x5a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2d, 0x6b, 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x6b, + 0x72, 0x61, 0x74, 0x6f, 0x73, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x62, + 0x6c, 0x6f, 0x67, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x76, 0x31, 0xa2, 0x02, 0x0d, + 0x41, 0x50, 0x49, 0x42, 0x6c, 0x6f, 0x67, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x73, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_error_reason_proto_rawDescOnce sync.Once + file_error_reason_proto_rawDescData = file_error_reason_proto_rawDesc +) + +func file_error_reason_proto_rawDescGZIP() []byte { + file_error_reason_proto_rawDescOnce.Do(func() { + file_error_reason_proto_rawDescData = protoimpl.X.CompressGZIP(file_error_reason_proto_rawDescData) + }) + return file_error_reason_proto_rawDescData +} + +var file_error_reason_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_error_reason_proto_goTypes = []interface{}{ + (ErrorReason)(0), // 0: errors.ErrorReason +} +var file_error_reason_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] 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_error_reason_proto_init() } +func file_error_reason_proto_init() { + if File_error_reason_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_error_reason_proto_rawDesc, + NumEnums: 1, + NumMessages: 0, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_error_reason_proto_goTypes, + DependencyIndexes: file_error_reason_proto_depIdxs, + EnumInfos: file_error_reason_proto_enumTypes, + }.Build() + File_error_reason_proto = out.File + file_error_reason_proto_rawDesc = nil + file_error_reason_proto_goTypes = nil + file_error_reason_proto_depIdxs = nil +} diff --git a/examples/errors/api/error_reason.proto b/examples/errors/api/error_reason.proto new file mode 100644 index 000000000..2b1a2c166 --- /dev/null +++ b/examples/errors/api/error_reason.proto @@ -0,0 +1,17 @@ +syntax = "proto3"; + +package errors; +import "errors.proto"; + +// 多语言特定包名,用于源代码引用 +option go_package = "github.com/go-kratos/kratos/examples/blog/api/v1;v1"; +option java_multiple_files = true; +option java_package = "blog.v1.errors"; +option objc_class_prefix = "APIBlogErrors"; + +enum ErrorReason { + option (errors.default_code) = 500; + + USER_NOT_FOUND = 0 [(errors.code) = 404]; + CONTENT_MISSING = 1 [(errors.code) = 400];; +} diff --git a/examples/errors/api/error_reason_errors.pb.go b/examples/errors/api/error_reason_errors.pb.go new file mode 100644 index 000000000..19190580a --- /dev/null +++ b/examples/errors/api/error_reason_errors.pb.go @@ -0,0 +1,30 @@ +// Code generated by protoc-gen-go-errors. DO NOT EDIT. + +package api + +import ( + fmt "fmt" + errors "github.com/go-kratos/kratos/v2/errors" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the kratos package it is being compiled against. +const _ = errors.SupportPackageIsVersion1 + +func IsUserNotFound(err error) bool { + e := errors.FromError(err) + return e.Reason == ErrorReason_USER_NOT_FOUND.String() && e.Code == 404 +} + +func ErrorUserNotFound(format string, args ...interface{}) *errors.Error { + return errors.New(404, ErrorReason_USER_NOT_FOUND.String(), fmt.Sprintf(format, args...)) +} + +func IsContentMissing(err error) bool { + e := errors.FromError(err) + return e.Reason == ErrorReason_CONTENT_MISSING.String() && e.Code == 400 +} + +func ErrorContentMissing(format string, args ...interface{}) *errors.Error { + return errors.New(400, ErrorReason_CONTENT_MISSING.String(), fmt.Sprintf(format, args...)) +} diff --git a/examples/errors/api/errors.proto b/examples/errors/api/errors.proto new file mode 100644 index 000000000..3603729ac --- /dev/null +++ b/examples/errors/api/errors.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package errors; + +option go_package = "github.com/go-kratos/kratos/v2/errors;v1"; +option java_multiple_files = true; +option java_package = "com.github.kratos.errors"; +option objc_class_prefix = "KratosErrors"; + +import "google/protobuf/descriptor.proto"; + +extend google.protobuf.EnumOptions { + int32 default_code = 1108; +} + +extend google.protobuf.EnumValueOptions { + int32 code = 1109; +} \ No newline at end of file diff --git a/examples/errors/client/main.go b/examples/errors/client/main.go new file mode 100644 index 000000000..7a5d9cdc7 --- /dev/null +++ b/examples/errors/client/main.go @@ -0,0 +1,62 @@ +package main + +import ( + "context" + "github.com/go-kratos/kratos/examples/errors/api" + "github.com/go-kratos/kratos/v2/errors" + "log" + + pb "github.com/go-kratos/kratos/examples/helloworld/helloworld" + transgrpc "github.com/go-kratos/kratos/v2/transport/grpc" + transhttp "github.com/go-kratos/kratos/v2/transport/http" +) + +func main() { + callHTTP() + callGRPC() +} + +func callHTTP() { + conn, err := transhttp.NewClient( + context.Background(), + transhttp.WithEndpoint("127.0.0.1:8000"), + ) + if err != nil { + panic(err) + } + client := pb.NewGreeterHTTPClient(conn) + reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "empty"}) + if err != nil { + if errors.Code(err) == 500 { + log.Println(err) + } + if api.IsUserNotFound(err) { + log.Println("[http] USER_NOT_FOUND_ERROR", err) + } + } else { + log.Printf("[http] SayHello %s\n", reply.Message) + } +} + +func callGRPC() { + conn, err := transgrpc.DialInsecure( + context.Background(), + transgrpc.WithEndpoint("127.0.0.1:9000"), + ) + if err != nil { + panic(err) + } + client := pb.NewGreeterClient(conn) + reply, err := client.SayHello(context.Background(), &pb.HelloRequest{Name: "kratos"}) + if err != nil { + e := errors.FromError(err) + if e.Reason == "USER_NAME_EMPTY" && e.Code == 500 { + log.Println("[grpc] USER_NAME_EMPTY", err) + } + if api.IsUserNotFound(err) { + log.Println("[grpc] USER_NOT_FOUND_ERROR", err) + } + } else { + log.Printf("[grpc] SayHello %+v\n", reply) + } +} diff --git a/examples/errors/server/main.go b/examples/errors/server/main.go new file mode 100644 index 000000000..7319554e4 --- /dev/null +++ b/examples/errors/server/main.go @@ -0,0 +1,65 @@ +package main + +import ( + "context" + "fmt" + "github.com/go-kratos/kratos/v2/errors" + "log" + + "github.com/go-kratos/kratos/examples/errors/api" + "github.com/go-kratos/kratos/examples/helloworld/helloworld" + "github.com/go-kratos/kratos/v2" + "github.com/go-kratos/kratos/v2/transport/grpc" + "github.com/go-kratos/kratos/v2/transport/http" +) + +// go build -ldflags "-X main.Version=x.y.z" +var ( + // Name is the name of the compiled software. + Name = "errors" + // Version is the version of the compiled software. + Version = "v1.0.0" +) + +// server is used to implement helloworld.GreeterServer. +type server struct { + helloworld.UnimplementedGreeterServer +} + +// SayHello implements helloworld.GreeterServer +func (s *server) SayHello(ctx context.Context, in *helloworld.HelloRequest) (*helloworld.HelloReply, error) { + fmt.Println(in.Name) + if in.Name == "empty" { + // Respond to errors through errors.New(). + return nil, errors.New(500, "USER_NAME_EMPTY", "user name is empty") + } + if in.Name == "kratos" { + // Respond to errors with proto generated code. + return nil, api.ErrorUserNotFound("user %s not found", "kratos") + } + return &helloworld.HelloReply{Message: fmt.Sprintf("Hello %+v", in.Name)}, nil +} + +func main() { + s := &server{} + grpcSrv := grpc.NewServer( + grpc.Address(":9000"), + ) + httpSrv := http.NewServer( + http.Address(":8000"), + ) + helloworld.RegisterGreeterServer(grpcSrv, s) + helloworld.RegisterGreeterHTTPServer(httpSrv, s) + + app := kratos.New( + kratos.Name(Name), + kratos.Server( + httpSrv, + grpcSrv, + ), + ) + + if err := app.Run(); err != nil { + log.Fatal(err) + } +}