Golang gRPC双向流未生成SendAndClose方法的解决问询
解决gRPC Go双向流接口缺少SendAndClose方法的问题
问题根源
你定义的LongGreet是双向流式RPC(stream GreetRequest returns stream GreetResponse),而SendAndClose方法仅属于客户端流式RPC(客户端发送多个请求,服务器仅返回一个响应的RPC类型)的服务器接口。双向流式RPC的服务器接口仅提供Send(多次发送响应)和Recv(接收客户端请求)方法,不存在SendAndClose。
两种解决方案
根据你的实际业务需求选择:
1. 改为客户端流式RPC(服务器仅返回一次响应)
如果你的需求是客户端发送多个请求,服务器最终返回一个汇总响应,修改greet.proto中的LongGreet定义:
service GreetService { rpc Greet (GreetRequest) returns (GreetResponse); rpc GreetManyTimes (GreetRequest) returns (stream GreetResponse); // 修改为客户端流式RPC:仅返回单个响应 rpc LongGreet (stream GreetRequest) returns (GreetResponse); }
重新执行protoc生成Go代码后,GreetService_LongGreetServer接口就会包含SendAndClose方法,此时你的原代码调用SendAndClose即可正常工作。
2. 保持双向流式RPC(服务器多次返回响应)
如果你的需求确实是双向流(服务器需要在客户端发送请求的过程中多次返回响应),则修改服务器端代码,移除SendAndClose调用,改用Send发送响应,最后通过返回error或nil结束流:
import "io" func (s *Server) LongGreet(stream pb.GreetService_LongGreetServer) error { var res string for { req, err := stream.Recv() if err == io.EOF { // 客户端已发送完所有请求,发送最终响应后结束 return stream.Send(&pb.GreetResponse{Result: res}) } if err != nil { return err } res += "Hello " + req.FirstName + "! " // 可随时发送中间响应 if err := stream.Send(&pb.GreetResponse{Result: "已收到你的请求: " + req.FirstName}); err != nil { return err } } }
额外验证
你参考的教程中使用SendAndClose的场景,对应的RPC类型应该是客户端流式RPC而非双向流式RPC,建议核对教程中的proto定义确认。
内容的提问来源于stack exchange,提问作者Igor-Men
相关产品推荐
相关产品推荐

