生成代码(传统非泛型)参考

生成代码(传统非泛型)参考

本页描述了在使用 `protoc` 编译 `.proto` 文件时,由 grpc 插件 `protoc-gen-go-grpc` 生成的代码。

你可以在服务定义中找到如何在 `.proto` 文件中定义 gRPC 服务。

线程安全:请注意,客户端 RPC 调用和服务器端 RPC 处理程序是线程安全的,并且旨在并发 goroutine 中运行。但也要注意,对于单个流,传入和传出的数据是双向但串行的;因此,例如,单个流不支持并发读取并发写入(但读取与写入可以安全地并发进行)。

生成服务器接口上的方法

在服务器端,`.proto` 文件中的每个 `service Bar` 都将生成函数

func RegisterBarServer(s *grpc.Server, srv BarServer)

应用程序可以定义 `BarServer` 接口的具体实现,并在启动服务器实例之前使用此函数将其注册到 `grpc.Server` 实例。

一元方法

这些方法在生成的服务接口上具有以下签名

Foo(context.Context, *MsgA) (*MsgB, error)

在此上下文中,`MsgA` 是客户端发送的 protobuf 消息,`MsgB` 是服务器返回的 protobuf 消息。

服务器流式方法

这些方法在生成的服务接口上具有以下签名

Foo(*MsgA, <ServiceName>_FooServer) error

在此上下文中,`MsgA` 是来自客户端的单个请求,而 `_FooServer` 参数表示从服务器到客户端的 `MsgB` 消息流。

`_FooServer` 包含一个嵌入的 `grpc.ServerStream` 和以下接口

type <ServiceName>_FooServer interface {
	Send(*MsgB) error
	grpc.ServerStream
}

服务器端处理程序可以通过此参数的 `Send` 方法向客户端发送 protobuf 消息流。服务器到客户端流的结束由处理程序方法的 `return` 引起。

客户端流式方法

这些方法在生成的服务接口上具有以下签名

Foo(<ServiceName>_FooServer) error

在此上下文中,`_FooServer` 既可用于读取客户端到服务器的消息流,也可用于发送单个服务器响应消息。

`_FooServer` 包含一个嵌入的 `grpc.ServerStream` 和以下接口

type <ServiceName>_FooServer interface {
	SendAndClose(*MsgA) error
	Recv() (*MsgB, error)
	grpc.ServerStream
}

服务器端处理程序可以重复调用此参数上的 `Recv` 以接收来自客户端的完整消息流。一旦到达流的末尾,`Recv` 将返回 `(nil, io.EOF)`。通过调用此 `_FooServer` 参数上的 `SendAndClose` 方法来发送来自服务器的单个响应消息。请注意,`SendAndClose` 必须且只能调用一次。

双向流式方法

这些方法在生成的服务接口上具有以下签名

Foo(<ServiceName>_FooServer) error

在此上下文中,`_FooServer` 可用于访问客户端到服务器的消息流和服务器到客户端的消息流。`_FooServer` 包含一个嵌入的 `grpc.ServerStream` 和以下接口

type <ServiceName>_FooServer interface {
	Send(*MsgA) error
	Recv() (*MsgB, error)
	grpc.ServerStream
}

服务器端处理程序可以重复调用此参数上的 `Recv` 以读取客户端到服务器的消息流。一旦到达客户端到服务器流的末尾,`Recv` 将返回 `(nil, io.EOF)`。通过重复调用此 `ServiceName>_FooServer` 参数上的 `Send` 方法来发送响应的服务器到客户端消息流。服务器到客户端流的结束由双向方法处理程序的 `return` 指示。

生成客户端接口上的方法

对于客户端使用,`.proto` 文件中的每个 `service Bar` 也生成函数:`func BarClient(cc *grpc.ClientConn) BarClient`,该函数返回 `BarClient` 接口的具体实现(此具体实现也位于生成的 `.pb.go` 文件中)。

一元方法

这些方法在生成的客户端存根上具有以下签名

(ctx context.Context, in *MsgA, opts ...grpc.CallOption) (*MsgB, error)

在此上下文中,`MsgA` 是从客户端到服务器的单个请求,`MsgB` 包含从服务器返回的响应。

服务器流式方法

这些方法在生成的客户端存根上具有以下签名

Foo(ctx context.Context, in *MsgA, opts ...grpc.CallOption) (<ServiceName>_FooClient, error)

在此上下文中,`_FooClient` 表示服务器到客户端的 `MsgB` 消息 `流`。

此流包含一个嵌入的 `grpc.ClientStream` 和以下接口

type <ServiceName>_FooClient interface {
	Recv() (*MsgB, error)
	grpc.ClientStream
}

当客户端在存根上调用 `Foo` 方法时,流开始。然后,客户端可以重复调用返回的 `_FooClient` *流*上的 `Recv` 方法,以读取服务器到客户端的响应流。一旦服务器到客户端流完全读取完毕,此 `Recv` 方法将返回 `(nil, io.EOF)`。

客户端流式方法

这些方法在生成的客户端存根上具有以下签名

Foo(ctx context.Context, opts ...grpc.CallOption) (<ServiceName>_FooClient, error)

在此上下文中,`_FooClient` 表示客户端到服务器的 `MsgA` 消息 `流`。

`_FooClient` 包含一个嵌入的 `grpc.ClientStream` 和以下接口

type <ServiceName>_FooClient interface {
	Send(*MsgA) error
	CloseAndRecv() (*MsgB, error)
	grpc.ClientStream
}

当客户端在存根上调用 `Foo` 方法时,流开始。然后,客户端可以重复调用返回的 `_FooClient` 流上的 `Send` 方法,以发送客户端到服务器的消息流。此流上的 `CloseAndRecv` 方法必须且只能调用一次,以同时关闭客户端到服务器流并接收来自服务器的单个响应消息。

双向流式方法

这些方法在生成的客户端存根上具有以下签名

Foo(ctx context.Context, opts ...grpc.CallOption) (<ServiceName>_FooClient, error)

在此上下文中,`_FooClient` 表示客户端到服务器和服务器到客户端的消息流。

`_FooClient` 包含一个嵌入的 `grpc.ClientStream` 和以下接口

type <ServiceName>_FooClient interface {
	Send(*MsgA) error
	Recv() (*MsgB, error)
	grpc.ClientStream
}

当客户端在存根上调用 `Foo` 方法时,流开始。然后,客户端可以重复调用返回的 `_FooClient` 流上的 `Send` 方法,以发送客户端到服务器的消息流。客户端还可以重复调用此流上的 `Recv` 以接收完整的服务器到客户端消息流。

服务器到客户端流的结束由流的 `Recv` 方法返回 `(nil, io.EOF)` 指示。客户端到服务器流的结束可以由客户端通过调用流上的 `CloseSend` 方法来指示。

包和命名空间

当使用 `--go_out=plugins=grpc:` 调用 `protoc` 编译器时,`proto package` 到 Go package 的转换与在不使用 `grpc` 插件的情况下使用 `protoc-gen-go` 插件时的工作方式相同。

因此,例如,如果 `foo.proto` 声明自己位于 `package foo` 中,则生成的 `foo.pb.go` 文件也将位于 Go `package foo` 中。