You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 19:59:52