Go-GRPC 初体验

grpc 跟常见的client-server模型相似(dubbo)
grpc 编码之前需要准备以下环境:

  • 安装protobuf,grpc的client与server之间消息传递使用的protoc格式消息,比起json,xml速度快
  • 安装grpc 的源码包

下面开始编写grpc示例代码:

  1. 首先编写proto文件,示例:helloworld
1syntax = "proto3"; 2 3option objc\_class\_prefix = "HLW"; 4 5package helloworld; 6 7// 定义一个Greeter服务,其中API为SayHello 8// 形式参数: HelloRequest 9// 返回参数:HelloReply 10service Greeter { 11 // Sends a greeting 12 rpc SayHello (HelloRequest) returns (HelloReply) {} 13 14 // rpc 借口的类型分为一下四种: A为接受参数,B为返回参数 15 // 1. rpc GetFeature(Point) returns (Feature) {} 普通调用:A-B 16 // 2. rpc ListFeatures(Rectangle) returns (stream Feature) {} 单向流:A - B(流) 17 // 3. rpc RecordRoute(stream Point) returns (RouteSummary) {} 单向流:A(流) - B 18 // 4. rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} 双向流:A(流) - B(流) 19} 20 21// 请求参数-根据自己的需求定义 22message HelloRequest { 23 string name = 1; 24} 25 26// 返回参数-根据自己的需求定义 27message HelloReply { 28 string message = 1; 29} 30

  2.  将helloworld.proto转化为helloworld.proto.go 

命令:protoc --go_out=plugins=grpc:. helloworld.proto 结果如下:

1// Code generated by protoc-gen-go. 2// source: helloworld.proto 3// DO NOT EDIT! 4 5/\* 6Package helloworld is a generated protocol buffer package. 7 8It is generated from these files: 9 helloworld.proto 10 11It has these top-level messages: 12 HelloRequest 13 HelloReply 14\*/ 15package myblogproto 16 17import proto "github.com/golang/protobuf/proto" 18import fmt "fmt" 19import math "math" 20 21import ( 22 context "golang.org/x/net/context" 23 grpc "google.golang.org/grpc" 24) 25 26// Reference imports to suppress errors if they are not otherwise used. 27var \_ = proto.Marshal 28var \_ = fmt.Errorf 29var \_ = math.Inf 30 31// This is a compile-time assertion to ensure that this generated file 32// is compatible with the proto package it is being compiled against. 33// A compilation error at this line likely means your copy of the 34// proto package needs to be updated. 35const \_ = proto.ProtoPackageIsVersion2 // please upgrade the proto package 36 37// 请求参数-根据自己的需求定义 38type HelloRequest struct { 39 Name string \`protobuf:"bytes,1,opt,name=name" json:"name,omitempty"\` 40} 41 42func (m \*HelloRequest) Reset() { \*m = HelloRequest{} } 43func (m \*HelloRequest) String() string { return proto.CompactTextString(m) } 44func (\*HelloRequest) ProtoMessage() {} 45func (\*HelloRequest) Descriptor() (\[\]byte, \[\]int) { return fileDescriptor0, \[\]int{0} } 46 47func (m \*HelloRequest) GetName() string { 48 if m != nil { 49 return m.Name 50 } 51 return "" 52} 53 54// 返回参数-根据自己的需求定义 55type HelloReply struct { 56 Message string \`protobuf:"bytes,1,opt,name=message" json:"message,omitempty"\` 57} 58 59func (m \*HelloReply) Reset() { \*m = HelloReply{} } 60func (m \*HelloReply) String() string { return proto.CompactTextString(m) } 61func (\*HelloReply) ProtoMessage() {} 62func (\*HelloReply) Descriptor() (\[\]byte, \[\]int) { return fileDescriptor0, \[\]int{1} } 63 64func (m \*HelloReply) GetMessage() string { 65 if m != nil { 66 return m.Message 67 } 68 return "" 69} 70 71func init() { 72 proto.RegisterType((\*HelloRequest)(nil), "helloworld.HelloRequest") 73 proto.RegisterType((\*HelloReply)(nil), "helloworld.HelloReply") 74} 75 76// Reference imports to suppress errors if they are not otherwise used. 77var \_ context.Context 78var \_ grpc.ClientConn 79 80// This is a compile-time assertion to ensure that this generated file 81// is compatible with the grpc package it is being compiled against. 82const \_ = grpc.SupportPackageIsVersion4 83 84// Client API for Greeter service 85 86type GreeterClient interface { 87 // Sends a greeting 88 SayHello(ctx context.Context, in \*HelloRequest, opts ...grpc.CallOption) (\*HelloReply, error) 89} 90 91type greeterClient struct { 92 cc \*grpc.ClientConn 93} 94 95func NewGreeterClient(cc \*grpc.ClientConn) GreeterClient { 96 return &greeterClient{cc} 97} 98 99func (c \*greeterClient) SayHello(ctx context.Context, in \*HelloRequest, opts ...grpc.CallOption) (\*HelloReply, error) { 100 out := new(HelloReply) 101 err := grpc.Invoke(ctx, "/helloworld.Greeter/SayHello", in, out, c.cc, opts...) 102 if err != nil { 103 return nil, err 104 } 105 return out, nil 106} 107 108// Server API for Greeter service 109 110type GreeterServer interface { 111 // Sends a greeting 112 SayHello(context.Context, \*HelloRequest) (\*HelloReply, error) 113} 114 115func RegisterGreeterServer(s \*grpc.Server, srv GreeterServer) { 116 s.RegisterService(&\_Greeter\_serviceDesc, srv) 117} 118 119func \_Greeter\_SayHello\_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 120 in := new(HelloRequest) 121 if err := dec(in); err != nil { 122 return nil, err 123 } 124 if interceptor == nil { 125 return srv.(GreeterServer).SayHello(ctx, in) 126 } 127 info := &grpc.UnaryServerInfo{ 128 Server: srv, 129 FullMethod: "/helloworld.Greeter/SayHello", 130 } 131 handler := func(ctx context.Context, req interface{}) (interface{}, error) { 132 return srv.(GreeterServer).SayHello(ctx, req.(\*HelloRequest)) 133 } 134 return interceptor(ctx, in, info, handler) 135} 136 137var \_Greeter\_serviceDesc = grpc.ServiceDesc{ 138 ServiceName: "helloworld.Greeter", 139 HandlerType: (\*GreeterServer)(nil), 140 Methods: \[\]grpc.MethodDesc{ 141 { 142 MethodName: "SayHello", 143 Handler: \_Greeter\_SayHello\_Handler, 144 }, 145 }, 146 Streams: \[\]grpc.StreamDesc{}, 147 Metadata: "helloworld.proto", 148} 149 150func init() { proto.RegisterFile("helloworld.proto", fileDescriptor0) } 151 152var fileDescriptor0 = \[\]byte{ 153 // 149 bytes of a gzipped FileDescriptorProto 154 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0x48, 0xcd, 0xc9, 155 0xc9, 0x2f, 0xcf, 0x2f, 0xca, 0x49, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x42, 0x88, 156 0x28, 0x29, 0x71, 0xf1, 0x78, 0x80, 0x78, 0x41, 0xa9, 0x85, 0xa5, 0xa9, 0xc5, 0x25, 0x42, 0x42, 157 0x5c, 0x2c, 0x79, 0x89, 0xb9, 0xa9, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x60, 0xb6, 0x92, 158 0x1a, 0x17, 0x17, 0x54, 0x4d, 0x41, 0x4e, 0xa5, 0x90, 0x04, 0x17, 0x7b, 0x6e, 0x6a, 0x71, 0x71, 159 0x62, 0x3a, 0x4c, 0x11, 0x8c, 0x6b, 0xe4, 0xc9, 0xc5, 0xee, 0x5e, 0x94, 0x9a, 0x5a, 0x92, 0x5a, 160 0x24, 0x64, 0xc7, 0xc5, 0x11, 0x9c, 0x58, 0x09, 0xd6, 0x25, 0x24, 0xa1, 0x87, 0xe4, 0x02, 0x64, 161 0xcb, 0xa4, 0xc4, 0xb0, 0xc8, 0x14, 0xe4, 0x54, 0x2a, 0x31, 0x38, 0xb1, 0x2d, 0x62, 0x62, 0xf6, 162 0xf0, 0x09, 0x4f, 0x62, 0x03, 0xbb, 0xd8, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0xbe, 0xde, 0x1d, 163 0x2e, 0xc5, 0x00, 0x00, 0x00, 164} 165

  3. 编写grpc服务端,伪代码:

1package main 2 3import ( 4 "fmt" 5 "golang.org/x/net/context" 6 "google.golang.org/grpc" 7 "net" 8 9 pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto" 10) 11 12const port = ":50051" 13 14// 定义struct实现我们自定义的helloworld.proto对应的服务 15type myServer struct { 16} 17 18func (m \*myServer) SayHello(ctx context.Context, in \*pb.HelloRequest) (\*pb.HelloReply, error) { 19 return &pb.HelloReply{"请求server端成功!"}, nil 20} 21 22/\*\* 23 1. 首先我们必须实现我们自定义rpc服务,例如:rpc SayHello()-在此我们可以实现我们自己的逻辑 24 2. 创建监听listener 25 3. 创建grpc的服务 26 4. 将我们的服务注册到grpc的server中 27 5. 启动grpc服务,将我们自定义的监听信息传递给grpc服务器 28 \*/ 29 30func main() { 31 32 // 创建server端监听端口 33 list, err := net.Listen("tcp", port) 34 if err != nil { 35 fmt.Println(err) 36 } 37 38 // 创建grpc的server 39 server := grpc.NewServer() 40 // 注册我们自定义的helloworld服务 41 pb.RegisterGreeterServer(server, &myServer{}) 42 43 // 启动grpc服务 44 fmt.Println("grpc 服务启动... ...") 45 server.Serve(list) 46} 47

  4. 编写client端代码,伪代码如下:

1package main 2 3import ( 4 "google.golang.org/grpc" 5 "fmt" 6 "context" 7 8 pb "unicontract-validate/tests/grpcStudy/mybloggrpc/myblogproto" 9) 10 11// 此处应与服务器端对应 12const address = "127.0.0.1:50051" 13 14/\*\* 15 1. 创建groc连接器 16 2. 创建grpc客户端,并将连接器赋值给客户端 17 3. 向grpc服务端发起请求 18 4. 获取grpc服务端返回的结果 19 \*/ 20func main() { 21 22 // 创建一个grpc连接器 23 conn, err := grpc.Dial(address, grpc.WithInsecure()) 24 if err != nil{ 25 fmt.Println(err) 26 } 27 // 当请求完毕后记得关闭连接,否则大量连接会占用资源 28 defer conn.Close() 29 30 // 创建grpc客户端 31 c := pb.NewGreeterClient(conn) 32 33 name := "我是客户端,正在请求服务端!!!" 34 // 客户端向grpc服务端发起请求 35 result, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:name}) 36 fmt.Println(name) 37 if err != nil{ 38 fmt.Println("请求失败!!!") 39 return 40 } 41 // 获取服务端返回的结果 42 fmt.Println(result.Message) 43} 44

  服务端结果:

  客户端请求之后结果:

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )