上一章我们简单介绍了一下grpc 概念方面的信息,这一章我们具体学习grpc 在golang的知识。
源码地址:
https://github.com/grpc/grpc-go/tree/master/examples/route_guide
关于protocol buffers 的相关信息我们这里暂不赘述,如果有读者对这部分的知识不熟悉可以参看以下链接学习。
http://doc.oschina.net/grpc?t=60133
先上我们的route_guide.proto 文件
// Interface exported by the server.
service RouteGuide {
// A simple RPC. 最基本的不含流式信息的rpc 接口
//
// Obtains the feature at a given position.
//
// A feature with an empty name is returned if there's no feature at the given
// position.
rpc GetFeature(Point) returns (Feature) {}
// A server-to-client streaming RPC. 服务器端是流式信息的接口
//
// Obtains the Features available within the given Rectangle. Results are
// streamed rather than returned at once (e.g. in a response message with a
// repeated field), as the rectangle may cover a large area and contain a
// huge number of features.
rpc ListFeatures(Rectangle) returns (stream Feature) {}
// A client-to-server streaming RPC. 客户端是流式信息的接口
//
// Accepts a stream of Points on a route being traversed, returning a
// RouteSummary when traversal is completed.
rpc RecordRoute(stream Point) returns (RouteSummary) {}
// A Bidirectional streaming RPC. //双端流式信息的接口
//
// Accepts a stream of RouteNotes sent while a route is being traversed,
// while receiving other RouteNotes (e.g. from other users).
rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
}
相信读者已经看出来了在我们定义的服务中,普通的rpc 与流式rpc是使用stream 进行标识。
当我们完成route_guide.proto 服务的定义后,接下来我们需要从 .proto 的服务定义中生成 gRPC 客户端和服务器端的接口。我们通过 protocol buffer 的编译器 protoc
以及一个特殊的 gRPC Go 插件来完成。
具体生成步骤我们可以参考关于protocol buffers 的链接进行学习,这部分暂时只介绍代码结构的内容。
我们会生成 route_guide.pb.go 这个文件,
文件内容包括:
- 所有用于填充,序列化和获取我们请求和响应消息类型的 protocol buffer 代码
- 一个为客户端调用定义在
RouteGuide
服务的方法的接口类型(或者 存根 ) - 一个为服务器使用定义在
RouteGuide
服务的方法去实现的接口类型(或者 存根 )
package routeguide
import (...)
/*
这部分是所有用于填充,序列化和获取我们请求和响应消息类型的 protocol buffer 代码,我们不用特别关注这些代码,所以由于篇幅的原因就不记录
如果有读者对着部分代码充满好奇可以 通过 https://github.com/grpc/grpc-go/blob/master/examples/route_guide/routeguide/route_guide.pb.go 查看
*/
// 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
// RouteGuideClient is the client API for RouteGuide service.
//
// 生成的RouteGuide 客户端接口代码
type RouteGuideClient interface {
// A simple RPC.
//
GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error)
// A server-to-client streaming RPC.
//
ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error)
// A client-to-server streaming RPC.
//
RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error)
// A Bidirectional streaming RPC.
RouteChat(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RouteChatClient, error)
}
type routeGuideClient struct {
cc *grpc.ClientConn
}
func NewRouteGuideClient(cc *grpc.ClientConn) RouteGuideClient {
return &routeGuideClient{cc}
}
func (c *routeGuideClient) GetFeature(ctx context.Context, in *Point, opts ...grpc.CallOption) (*Feature, error) {
out := new(Feature)
err := c.cc.Invoke(ctx, "/routeguide.RouteGuide/GetFeature", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *routeGuideClient) ListFeatures(ctx context.Context, in *Rectangle, opts ...grpc.CallOption) (RouteGuide_ListFeaturesClient, error) {
stream, err := c.cc.NewStream(ctx, &_RouteGuide_serviceDesc.Streams[0], "/routeguide.RouteGuide/ListFeatures", opts...)
if err != nil {
return nil, err
}
x := &routeGuideListFeaturesClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type RouteGuide_ListFeaturesClient interface {
Recv() (*Feature, error)
grpc.ClientStream
}
type routeGuideListFeaturesClient struct {
grpc.ClientStream
}
func (x *routeGuideListFeaturesClient) Recv() (*Feature, error) {
m := new(Feature)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *routeGuideClient) RecordRoute(ctx context.Context, opts ...grpc.CallOption) (RouteGuide_RecordRouteClient, error) {
st