From cedb477402e017bf322b75ab37853042b224fb79 Mon Sep 17 00:00:00 2001 From: guoqiang Date: Sun, 17 Dec 2023 15:48:47 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0db=E6=93=8D=E4=BD=9C=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + consuldemo/pb/hello.pb.go | 505 ++++++++++++++++++++++++++-- consuldemo/pb/hello_grpc.pb.go | 111 ++++++ consuldemo/pkg/db/conn/mysql.go | 53 +++ consuldemo/pkg/db/query.sql | 14 + consuldemo/pkg/db/schema.sql | 14 + consuldemo/pkg/db/sqlc.yaml | 9 + consuldemo/pkg/db/user/db.go | 31 ++ consuldemo/pkg/db/user/models.go | 25 ++ consuldemo/pkg/db/user/query.sql.go | 128 +++++++ consuldemo/proto/hello.proto | 37 ++ consuldemo/server/main.go | 141 +++++++- go.mod | 2 + go.sum | 4 + 14 files changed, 1052 insertions(+), 23 deletions(-) create mode 100644 consuldemo/pkg/db/conn/mysql.go create mode 100644 consuldemo/pkg/db/query.sql create mode 100644 consuldemo/pkg/db/schema.sql create mode 100644 consuldemo/pkg/db/sqlc.yaml create mode 100644 consuldemo/pkg/db/user/db.go create mode 100644 consuldemo/pkg/db/user/models.go create mode 100644 consuldemo/pkg/db/user/query.sql.go diff --git a/.gitignore b/.gitignore index b19c8f3..aab3831 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ go.work .idea .DS_Store +vendor diff --git a/consuldemo/pb/hello.pb.go b/consuldemo/pb/hello.pb.go index 6950b1c..e437a68 100644 --- a/consuldemo/pb/hello.pb.go +++ b/consuldemo/pb/hello.pb.go @@ -114,6 +114,344 @@ func (x *GreetResponse) GetResult() string { return "" } +type CreateUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Mobile string `protobuf:"bytes,2,opt,name=mobile,proto3" json:"mobile,omitempty"` + Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` + Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"` +} + +func (x *CreateUserRequest) Reset() { + *x = CreateUserRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateUserRequest) ProtoMessage() {} + +func (x *CreateUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_hello_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 CreateUserRequest.ProtoReflect.Descriptor instead. +func (*CreateUserRequest) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateUserRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *CreateUserRequest) GetMobile() string { + if x != nil { + return x.Mobile + } + return "" +} + +func (x *CreateUserRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +func (x *CreateUserRequest) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +type CreateUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *CreateUserResponse) Reset() { + *x = CreateUserResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateUserResponse) ProtoMessage() {} + +func (x *CreateUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_hello_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 CreateUserResponse.ProtoReflect.Descriptor instead. +func (*CreateUserResponse) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{3} +} + +func (x *CreateUserResponse) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +type GetUserRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetUserRequest) Reset() { + *x = GetUserRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserRequest) ProtoMessage() {} + +func (x *GetUserRequest) ProtoReflect() protoreflect.Message { + mi := &file_hello_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 GetUserRequest.ProtoReflect.Descriptor instead. +func (*GetUserRequest) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{4} +} + +func (x *GetUserRequest) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +type GetUserResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + Username string `protobuf:"bytes,2,opt,name=username,proto3" json:"username,omitempty"` + Mobile string `protobuf:"bytes,3,opt,name=mobile,proto3" json:"mobile,omitempty"` + Email string `protobuf:"bytes,4,opt,name=email,proto3" json:"email,omitempty"` +} + +func (x *GetUserResponse) Reset() { + *x = GetUserResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetUserResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetUserResponse) ProtoMessage() {} + +func (x *GetUserResponse) ProtoReflect() protoreflect.Message { + mi := &file_hello_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 GetUserResponse.ProtoReflect.Descriptor instead. +func (*GetUserResponse) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{5} +} + +func (x *GetUserResponse) GetId() int64 { + if x != nil { + return x.Id + } + return 0 +} + +func (x *GetUserResponse) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *GetUserResponse) GetMobile() string { + if x != nil { + return x.Mobile + } + return "" +} + +func (x *GetUserResponse) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +type CheckPasswordRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` + Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` +} + +func (x *CheckPasswordRequest) Reset() { + *x = CheckPasswordRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckPasswordRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckPasswordRequest) ProtoMessage() {} + +func (x *CheckPasswordRequest) ProtoReflect() protoreflect.Message { + mi := &file_hello_proto_msgTypes[6] + 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 CheckPasswordRequest.ProtoReflect.Descriptor instead. +func (*CheckPasswordRequest) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{6} +} + +func (x *CheckPasswordRequest) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + +func (x *CheckPasswordRequest) GetPassword() string { + if x != nil { + return x.Password + } + return "" +} + +type CheckPasswordResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ok bool `protobuf:"varint,1,opt,name=ok,proto3" json:"ok,omitempty"` +} + +func (x *CheckPasswordResponse) Reset() { + *x = CheckPasswordResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_hello_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CheckPasswordResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckPasswordResponse) ProtoMessage() {} + +func (x *CheckPasswordResponse) ProtoReflect() protoreflect.Message { + mi := &file_hello_proto_msgTypes[7] + 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 CheckPasswordResponse.ProtoReflect.Descriptor instead. +func (*CheckPasswordResponse) Descriptor() ([]byte, []int) { + return file_hello_proto_rawDescGZIP(), []int{7} +} + +func (x *CheckPasswordResponse) GetOk() bool { + if x != nil { + return x.Ok + } + return false +} + var File_hello_proto protoreflect.FileDescriptor var file_hello_proto_rawDesc = []byte{ @@ -123,20 +461,59 @@ var file_hello_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x67, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x27, 0x0a, 0x0d, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x85, 0x01, 0x0a, 0x0c, 0x47, 0x72, - 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x47, 0x72, - 0x65, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x79, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x12, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, - 0x01, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x2e, 0x67, 0x71, 0x6e, 0x6f, 0x74, 0x65, 0x73, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x75, 0x6f, 0x71, 0x69, 0x61, 0x6e, 0x67, 0x2f, 0x67, 0x72, - 0x70, 0x63, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, 0x73, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x09, 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x79, 0x0a, 0x11, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x6f, + 0x62, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, 0x69, + 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x24, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x20, 0x0a, 0x0e, 0x47, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x6b, 0x0a, 0x0f, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, + 0x6f, 0x62, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x6f, 0x62, + 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4e, 0x0a, 0x14, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, + 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x27, 0x0a, 0x15, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x02, + 0x6f, 0x6b, 0x32, 0xd4, 0x02, 0x0a, 0x0c, 0x47, 0x72, 0x65, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x05, 0x47, 0x72, 0x65, 0x65, 0x74, 0x12, 0x13, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x3f, 0x0a, 0x0e, 0x47, 0x72, 0x65, + 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x13, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x72, 0x65, 0x65, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3a, 0x0a, 0x07, 0x47, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x0d, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1b, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, + 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, + 0x2e, 0x67, 0x71, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x75, 0x6f, + 0x71, 0x69, 0x61, 0x6e, 0x67, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x65, 0x78, 0x65, 0x72, 0x63, 0x69, + 0x73, 0x65, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x64, 0x65, 0x6d, 0x6f, 0x2f, 0x70, + 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -151,18 +528,30 @@ func file_hello_proto_rawDescGZIP() []byte { return file_hello_proto_rawDescData } -var file_hello_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_hello_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_hello_proto_goTypes = []interface{}{ - (*GreetRequest)(nil), // 0: proto.GreetRequest - (*GreetResponse)(nil), // 1: proto.GreetResponse + (*GreetRequest)(nil), // 0: proto.GreetRequest + (*GreetResponse)(nil), // 1: proto.GreetResponse + (*CreateUserRequest)(nil), // 2: proto.CreateUserRequest + (*CreateUserResponse)(nil), // 3: proto.CreateUserResponse + (*GetUserRequest)(nil), // 4: proto.GetUserRequest + (*GetUserResponse)(nil), // 5: proto.GetUserResponse + (*CheckPasswordRequest)(nil), // 6: proto.CheckPasswordRequest + (*CheckPasswordResponse)(nil), // 7: proto.CheckPasswordResponse } var file_hello_proto_depIdxs = []int32{ 0, // 0: proto.GreetService.Greet:input_type -> proto.GreetRequest 0, // 1: proto.GreetService.GreetManyTimes:input_type -> proto.GreetRequest - 1, // 2: proto.GreetService.Greet:output_type -> proto.GreetResponse - 1, // 3: proto.GreetService.GreetManyTimes:output_type -> proto.GreetResponse - 2, // [2:4] is the sub-list for method output_type - 0, // [0:2] is the sub-list for method input_type + 4, // 2: proto.GreetService.GetUser:input_type -> proto.GetUserRequest + 2, // 3: proto.GreetService.CreateUser:input_type -> proto.CreateUserRequest + 6, // 4: proto.GreetService.CheckPassword:input_type -> proto.CheckPasswordRequest + 1, // 5: proto.GreetService.Greet:output_type -> proto.GreetResponse + 1, // 6: proto.GreetService.GreetManyTimes:output_type -> proto.GreetResponse + 5, // 7: proto.GreetService.GetUser:output_type -> proto.GetUserResponse + 3, // 8: proto.GreetService.CreateUser:output_type -> proto.CreateUserResponse + 7, // 9: proto.GreetService.CheckPassword:output_type -> proto.CheckPasswordResponse + 5, // [5:10] is the sub-list for method output_type + 0, // [0:5] 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 @@ -198,6 +587,78 @@ func file_hello_proto_init() { return nil } } + file_hello_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateUserRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateUserResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetUserResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckPasswordRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_hello_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CheckPasswordResponse); 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{ @@ -205,7 +666,7 @@ func file_hello_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_hello_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/consuldemo/pb/hello_grpc.pb.go b/consuldemo/pb/hello_grpc.pb.go index a126bf4..e2b1a84 100644 --- a/consuldemo/pb/hello_grpc.pb.go +++ b/consuldemo/pb/hello_grpc.pb.go @@ -21,6 +21,9 @@ const _ = grpc.SupportPackageIsVersion7 const ( GreetService_Greet_FullMethodName = "/proto.GreetService/Greet" GreetService_GreetManyTimes_FullMethodName = "/proto.GreetService/GreetManyTimes" + GreetService_GetUser_FullMethodName = "/proto.GreetService/GetUser" + GreetService_CreateUser_FullMethodName = "/proto.GreetService/CreateUser" + GreetService_CheckPassword_FullMethodName = "/proto.GreetService/CheckPassword" ) // GreetServiceClient is the client API for GreetService service. @@ -29,6 +32,9 @@ const ( type GreetServiceClient interface { Greet(ctx context.Context, in *GreetRequest, opts ...grpc.CallOption) (*GreetResponse, error) GreetManyTimes(ctx context.Context, in *GreetRequest, opts ...grpc.CallOption) (GreetService_GreetManyTimesClient, error) + GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*GetUserResponse, error) + CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) + CheckPassword(ctx context.Context, in *CheckPasswordRequest, opts ...grpc.CallOption) (*CheckPasswordResponse, error) } type greetServiceClient struct { @@ -80,12 +86,42 @@ func (x *greetServiceGreetManyTimesClient) Recv() (*GreetResponse, error) { return m, nil } +func (c *greetServiceClient) GetUser(ctx context.Context, in *GetUserRequest, opts ...grpc.CallOption) (*GetUserResponse, error) { + out := new(GetUserResponse) + err := c.cc.Invoke(ctx, GreetService_GetUser_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greetServiceClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) { + out := new(CreateUserResponse) + err := c.cc.Invoke(ctx, GreetService_CreateUser_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *greetServiceClient) CheckPassword(ctx context.Context, in *CheckPasswordRequest, opts ...grpc.CallOption) (*CheckPasswordResponse, error) { + out := new(CheckPasswordResponse) + err := c.cc.Invoke(ctx, GreetService_CheckPassword_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // GreetServiceServer is the server API for GreetService service. // All implementations must embed UnimplementedGreetServiceServer // for forward compatibility type GreetServiceServer interface { Greet(context.Context, *GreetRequest) (*GreetResponse, error) GreetManyTimes(*GreetRequest, GreetService_GreetManyTimesServer) error + GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error) + CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) + CheckPassword(context.Context, *CheckPasswordRequest) (*CheckPasswordResponse, error) mustEmbedUnimplementedGreetServiceServer() } @@ -99,6 +135,15 @@ func (UnimplementedGreetServiceServer) Greet(context.Context, *GreetRequest) (*G func (UnimplementedGreetServiceServer) GreetManyTimes(*GreetRequest, GreetService_GreetManyTimesServer) error { return status.Errorf(codes.Unimplemented, "method GreetManyTimes not implemented") } +func (UnimplementedGreetServiceServer) GetUser(context.Context, *GetUserRequest) (*GetUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetUser not implemented") +} +func (UnimplementedGreetServiceServer) CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented") +} +func (UnimplementedGreetServiceServer) CheckPassword(context.Context, *CheckPasswordRequest) (*CheckPasswordResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CheckPassword not implemented") +} func (UnimplementedGreetServiceServer) mustEmbedUnimplementedGreetServiceServer() {} // UnsafeGreetServiceServer may be embedded to opt out of forward compatibility for this service. @@ -151,6 +196,60 @@ func (x *greetServiceGreetManyTimesServer) Send(m *GreetResponse) error { return x.ServerStream.SendMsg(m) } +func _GreetService_GetUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreetServiceServer).GetUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GreetService_GetUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreetServiceServer).GetUser(ctx, req.(*GetUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GreetService_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateUserRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreetServiceServer).CreateUser(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GreetService_CreateUser_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreetServiceServer).CreateUser(ctx, req.(*CreateUserRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _GreetService_CheckPassword_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CheckPasswordRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(GreetServiceServer).CheckPassword(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: GreetService_CheckPassword_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(GreetServiceServer).CheckPassword(ctx, req.(*CheckPasswordRequest)) + } + return interceptor(ctx, in, info, handler) +} + // GreetService_ServiceDesc is the grpc.ServiceDesc for GreetService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -162,6 +261,18 @@ var GreetService_ServiceDesc = grpc.ServiceDesc{ MethodName: "Greet", Handler: _GreetService_Greet_Handler, }, + { + MethodName: "GetUser", + Handler: _GreetService_GetUser_Handler, + }, + { + MethodName: "CreateUser", + Handler: _GreetService_CreateUser_Handler, + }, + { + MethodName: "CheckPassword", + Handler: _GreetService_CheckPassword_Handler, + }, }, Streams: []grpc.StreamDesc{ { diff --git a/consuldemo/pkg/db/conn/mysql.go b/consuldemo/pkg/db/conn/mysql.go new file mode 100644 index 0000000..f8d7c76 --- /dev/null +++ b/consuldemo/pkg/db/conn/mysql.go @@ -0,0 +1,53 @@ +package conn + +import ( + "database/sql" + "fmt" + _ "github.com/go-sql-driver/mysql" + "github.com/pkg/errors" + "log" +) + +type MySQLConn struct { + Host string + Port int + Username string + Password string + DBName string +} + +var mysqlDB *sql.DB + +// InitMySQLConn 初始化mysql连接 +func InitMySQLConn(cfg *MySQLConn) error { + var err error + mysqlDB, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", cfg.Username, cfg.Password, cfg.Host, cfg.Port, cfg.DBName)) + + if err != nil { + return errors.Wrap(err, "open mysql failed") + } + + mysqlDB.SetMaxIdleConns(5) + mysqlDB.SetMaxOpenConns(50) + + // ping + if err = mysqlDB.Ping(); err != nil { + return errors.Wrap(err, "ping mysql failed") + } + + log.Printf("connect mysql successfully, host:%s, port:%d\n", cfg.Host, cfg.Port) + + return nil +} + +func GetMySQLConn() *sql.DB { + return mysqlDB +} + +func CloseMySQLConn() error { + if mysqlDB == nil { + return nil + } + + return mysqlDB.Close() +} diff --git a/consuldemo/pkg/db/query.sql b/consuldemo/pkg/db/query.sql new file mode 100644 index 0000000..a1d454c --- /dev/null +++ b/consuldemo/pkg/db/query.sql @@ -0,0 +1,14 @@ +-- name: CreateUser :execresult +INSERT INTO grpcstudy.user (username, mobile, email, password) VALUES (?, ?, ?, ?); + +-- name: GetUserById :one +SELECT * FROM grpcstudy.user WHERE id = ? LIMIT 1; + +-- name: GetUserByUsername :one +SELECT * FROM grpcstudy.user WHERE username = ? LIMIT 1; + +-- name: GetUserByMobile :one +SELECT * FROM grpcstudy.user WHERE mobile = ? LIMIT 1; + +-- name: ListUsers :many +SELECT * FROM grpcstudy.user ORDER BY id DESC LIMIT ? OFFSET ?; diff --git a/consuldemo/pkg/db/schema.sql b/consuldemo/pkg/db/schema.sql new file mode 100644 index 0000000..944a29d --- /dev/null +++ b/consuldemo/pkg/db/schema.sql @@ -0,0 +1,14 @@ +create database if not exists `grpcstudy`; + +CREATE TABLE grpcstudy.`user` ( + `id` int unsigned NOT NULL AUTO_INCREMENT, + `username` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名', + `mobile` char(11) NOT NULL COMMENT '手机号', + `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '' COMMENT '邮箱', + `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '添加时间', + `modified_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + `password` varbinary(60) NOT NULL DEFAULT '' COMMENT '密码hash', + PRIMARY KEY (`id`), + UNIQUE KEY `udx_mobile` (`mobile`) USING BTREE, + UNIQUE KEY `udx_email` (`email`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci; diff --git a/consuldemo/pkg/db/sqlc.yaml b/consuldemo/pkg/db/sqlc.yaml new file mode 100644 index 0000000..0b1cb78 --- /dev/null +++ b/consuldemo/pkg/db/sqlc.yaml @@ -0,0 +1,9 @@ +version: "2" +sql: + - engine: "mysql" + queries: "query.sql" + schema: "schema.sql" + gen: + go: + package: "user" + out: "user" diff --git a/consuldemo/pkg/db/user/db.go b/consuldemo/pkg/db/user/db.go new file mode 100644 index 0000000..7046cda --- /dev/null +++ b/consuldemo/pkg/db/user/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.20.0 + +package user + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/consuldemo/pkg/db/user/models.go b/consuldemo/pkg/db/user/models.go new file mode 100644 index 0000000..5075814 --- /dev/null +++ b/consuldemo/pkg/db/user/models.go @@ -0,0 +1,25 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.20.0 + +package user + +import ( + "time" +) + +type GrpcstudyUser struct { + ID uint32 + // 用户名 + Username string + // 手机号 + Mobile string + // 邮箱 + Email string + // 添加时间 + CreatedAt time.Time + // 更新时间 + ModifiedAt time.Time + // 密码hash + Password []byte +} diff --git a/consuldemo/pkg/db/user/query.sql.go b/consuldemo/pkg/db/user/query.sql.go new file mode 100644 index 0000000..038e866 --- /dev/null +++ b/consuldemo/pkg/db/user/query.sql.go @@ -0,0 +1,128 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.20.0 +// source: query.sql + +package user + +import ( + "context" + "database/sql" +) + +const createUser = `-- name: CreateUser :execresult +INSERT INTO grpcstudy.user (username, mobile, email, password) VALUES (?, ?, ?, ?) +` + +type CreateUserParams struct { + Username string + Mobile string + Email string + Password []byte +} + +func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (sql.Result, error) { + return q.db.ExecContext(ctx, createUser, + arg.Username, + arg.Mobile, + arg.Email, + arg.Password, + ) +} + +const getUserById = `-- name: GetUserById :one +SELECT id, username, mobile, email, created_at, modified_at, password FROM grpcstudy.user WHERE id = ? LIMIT 1 +` + +func (q *Queries) GetUserById(ctx context.Context, id uint32) (GrpcstudyUser, error) { + row := q.db.QueryRowContext(ctx, getUserById, id) + var i GrpcstudyUser + err := row.Scan( + &i.ID, + &i.Username, + &i.Mobile, + &i.Email, + &i.CreatedAt, + &i.ModifiedAt, + &i.Password, + ) + return i, err +} + +const getUserByMobile = `-- name: GetUserByMobile :one +SELECT id, username, mobile, email, created_at, modified_at, password FROM grpcstudy.user WHERE mobile = ? LIMIT 1 +` + +func (q *Queries) GetUserByMobile(ctx context.Context, mobile string) (GrpcstudyUser, error) { + row := q.db.QueryRowContext(ctx, getUserByMobile, mobile) + var i GrpcstudyUser + err := row.Scan( + &i.ID, + &i.Username, + &i.Mobile, + &i.Email, + &i.CreatedAt, + &i.ModifiedAt, + &i.Password, + ) + return i, err +} + +const getUserByUsername = `-- name: GetUserByUsername :one +SELECT id, username, mobile, email, created_at, modified_at, password FROM grpcstudy.user WHERE username = ? LIMIT 1 +` + +func (q *Queries) GetUserByUsername(ctx context.Context, username string) (GrpcstudyUser, error) { + row := q.db.QueryRowContext(ctx, getUserByUsername, username) + var i GrpcstudyUser + err := row.Scan( + &i.ID, + &i.Username, + &i.Mobile, + &i.Email, + &i.CreatedAt, + &i.ModifiedAt, + &i.Password, + ) + return i, err +} + +const listUsers = `-- name: ListUsers :many +SELECT id, username, mobile, email, created_at, modified_at, password FROM grpcstudy.user ORDER BY id DESC LIMIT ? OFFSET ? +` + +type ListUsersParams struct { + Limit int32 + Offset int32 +} + +func (q *Queries) ListUsers(ctx context.Context, arg ListUsersParams) ([]GrpcstudyUser, error) { + rows, err := q.db.QueryContext(ctx, listUsers, arg.Limit, arg.Offset) + if err != nil { + return nil, err + } + defer rows.Close() + var items []GrpcstudyUser + for rows.Next() { + var i GrpcstudyUser + if err := rows.Scan( + &i.ID, + &i.Username, + &i.Mobile, + &i.Email, + &i.CreatedAt, + &i.ModifiedAt, + &i.Password, + ); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/consuldemo/proto/hello.proto b/consuldemo/proto/hello.proto index 3397312..914d145 100644 --- a/consuldemo/proto/hello.proto +++ b/consuldemo/proto/hello.proto @@ -7,6 +7,9 @@ option go_package = "git.gqnotes.com/guoqiang/grpcexercises/consuldemo/pb"; service GreetService { rpc Greet(GreetRequest) returns (GreetResponse) {} rpc GreetManyTimes(GreetRequest) returns (stream GreetResponse) {} + rpc GetUser(GetUserRequest) returns (GetUserResponse) {} + rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) {} + rpc CheckPassword(CheckPasswordRequest) returns (CheckPasswordResponse) {} } message GreetRequest { @@ -16,3 +19,37 @@ message GreetRequest { message GreetResponse { string result = 1; } + + + + +message CreateUserRequest { + string username = 1; + string mobile = 2; + string password = 3; + string email = 4; +} + +message CreateUserResponse { + int64 id = 1; +} + +message GetUserRequest { + int64 id = 1; +} + +message GetUserResponse { + int64 id = 1; + string username = 2; + string mobile = 3; + string email = 4; +} + +message CheckPasswordRequest { + string username = 1; + string password = 2; +} + +message CheckPasswordResponse { + bool ok = 1; +} diff --git a/consuldemo/server/main.go b/consuldemo/server/main.go index e73ab09..ee75945 100644 --- a/consuldemo/server/main.go +++ b/consuldemo/server/main.go @@ -2,9 +2,17 @@ package main import ( "context" + "database/sql" + "fmt" "git.gqnotes.com/guoqiang/grpcexercises/consuldemo/pkg/consul" + "git.gqnotes.com/guoqiang/grpcexercises/consuldemo/pkg/db/conn" + "git.gqnotes.com/guoqiang/grpcexercises/consuldemo/pkg/db/user" "github.com/hashicorp/consul/api" + "github.com/pkg/errors" + "golang.org/x/crypto/bcrypt" + "google.golang.org/grpc/codes" "google.golang.org/grpc/reflection" + "google.golang.org/grpc/status" "log" "net" "net/http" @@ -35,7 +43,7 @@ func main() { s := grpc.NewServer() - pb.RegisterGreetServiceServer(s, &Server{}) + pb.RegisterGreetServiceServer(s, &Server{logger: logger}) reflection.Register(s) @@ -44,6 +52,16 @@ func main() { // 启动相关服务 var gg errgroup.Group + gg.Go(func() error { + return conn.InitMySQLConn(&conn.MySQLConn{ + Host: "localhost", + Port: 3306, + Username: "test1", + Password: "test1", + DBName: "grpcstudy", + }) + }) + gg.Go(func() error { logger.Debug("grpc server start") @@ -129,6 +147,7 @@ func main() { type Server struct { pb.UnimplementedGreetServiceServer + logger *zap.Logger } func (s *Server) Greet(ctx context.Context, req *pb.GreetRequest) (resp *pb.GreetResponse, err error) { @@ -160,3 +179,123 @@ func (s *Server) GreetManyTimes(request *pb.GreetRequest, stream pb.GreetService return } + +// CreateUser 创建用户 +func (s *Server) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (resp *pb.CreateUserResponse, err error) { + resp = &pb.CreateUserResponse{} + + // 获取密码hash值 + passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), 12) + + if err != nil { + err = status.Error(codes.Internal, "password hash failed:"+err.Error()) + return + } + + queries := user.New(conn.GetMySQLConn()) + result, err := queries.CreateUser(ctx, user.CreateUserParams{ + Username: req.Username, + Mobile: req.Mobile, + Email: req.Email, + Password: passwordHash, + }) + + if err != nil { + err = status.Error(codes.Internal, "create user failed:"+err.Error()) + return + } + + // 获取插入的id + id, err := result.LastInsertId() + + if err != nil { + err = status.Error(codes.Internal, "create user failed") + return + } + + resp.Id = id + + return +} + +// GetUser 获取用户 +func (s *Server) GetUser(ctx context.Context, req *pb.GetUserRequest) (resp *pb.GetUserResponse, err error) { + resp = &pb.GetUserResponse{} + + defer func() { + if err1 := recover(); err1 != nil { + s.logger.Fatal("get user failed", zap.Any("err", err1)) + err = status.Error(codes.Internal, fmt.Sprintf("panic: %v", err1)) + } + + if err != nil { + s.logger.Error("get user failed", zap.Error(err)) + } else { + s.logger.Info("get user success") + } + }() + + queries := user.New(conn.GetMySQLConn()) + + result, err := queries.GetUserById(ctx, uint32(req.Id)) + + if err != nil { + if !errors.Is(err, sql.ErrNoRows) { + err = status.Error(codes.Internal, "get user failed") + return + } + + err = status.Error(codes.NotFound, "user not found") + return + } + + resp.Id = int64(result.ID) + resp.Username = result.Username + resp.Mobile = result.Mobile + resp.Email = result.Email + + return +} + +// CheckPassword 校验密码 +func (s *Server) CheckPassword(ctx context.Context, req *pb.CheckPasswordRequest) (resp *pb.CheckPasswordResponse, err error) { + resp = &pb.CheckPasswordResponse{} + + defer func() { + if err1 := recover(); err1 != nil { + s.logger.Fatal("check password failed", zap.Any("err", err1)) + err = status.Error(codes.Internal, fmt.Sprintf("panic: %v", err1)) + } + + if err != nil { + s.logger.Error("check password failed", zap.Error(err)) + } else { + s.logger.Info("check password success") + } + }() + + queries := user.New(conn.GetMySQLConn()) + + // 查询用户信息 + result, err := queries.GetUserByUsername(ctx, req.Username) + + if err != nil { + if !errors.Is(err, sql.ErrNoRows) { + err = status.Error(codes.Internal, "check password failed:"+err.Error()) + return + } + + err = status.Error(codes.NotFound, "user not found") + return + } + + // 校验密码 + if err = bcrypt.CompareHashAndPassword(result.Password, []byte(req.Password)); err != nil { + err = status.Error(codes.Unauthenticated, "password incorrect") + return + } + + resp.Ok = true + + return +} diff --git a/go.mod b/go.mod index 81d2a0c..30de0a6 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,11 @@ module git.gqnotes.com/guoqiang/grpcexercises go 1.21.4 require ( + github.com/go-sql-driver/mysql v1.7.1 github.com/hashicorp/consul/api v1.26.1 github.com/pkg/errors v0.9.1 go.uber.org/zap v1.26.0 + golang.org/x/crypto v0.14.0 golang.org/x/sync v0.3.0 google.golang.org/grpc v1.59.0 google.golang.org/protobuf v1.31.0 diff --git a/go.sum b/go.sum index 66e0810..102d851 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2 github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -176,6 +178,8 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=