Search code examples
goprotocol-buffersgrpc

Golang proto not generate method SendAndClose for stream


Just start to looking how to configure grpc by examples (i am new into grpc, golang). I tried to build bidirectional stream using this greet.proto file

message GreetRequest {
  string first_name = 1;
}

message GreetResponse {
  string result = 1;
}

service GreetService {
  rpc Greet (GreetRequest) returns (GreetResponse);
  rpc GreetManyTimes (GreetRequest) returns (stream GreetResponse);
  rpc LongGreet (stream GreetRequest) returns (stream GreetResponse);
}

this resulted in greet_rpc.pb.go:

type GreetService_LongGreetServer interface {
    Send(*GreetResponse) error
    Recv() (*GreetRequest, error)
    grpc.ServerStream
}

but generated file is missing method SendAndClose

and into long_greet.go

where i want use

func (s *Server) LongGreet(stream pb.GreetService_LongGreetServer) error {
    .....
    return stream.SendAndClose(&pb.GreetResponse{
        Result: res,
    })

I got error like:

GreetService_LongGreetServer has no field or method SendAndClose

question: how to generate that method SendAndClose into greet_rpc.pb.go?

I tried to research similar tuts and didnt find solution, all of them use that method. link to tutorial

This is go.mod:

module github.com/Igor-Men/grpc-go
    
go 1.21
    
toolchain go1.22.5
    
require (
    google.golang.org/grpc v1.65.0
    google.golang.org/protobuf v1.34.2
)
    
require (
    golang.org/x/net v0.27.0 // indirect
    golang.org/x/sys v0.22.0 // indirect
    golang.org/x/text v0.16.0 // indirect
    google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
)
protoc --version
libprotoc 27.2

Solution

  • The basics tutorial details four types of gRPC calls (in summary, see the tutorial for more detail):

    • Simple RPC call (request and response).
    • Server-side streaming RPC (client sends a request and server returns a stream)
    • Client-side streaming RPC (client sends stream, gets single response)
    • Bidirectional streaming RPC (both sides stream).

    The example you linked is a client side stream:

    rpc LongGreet(stream GreetRequest) returns (GreetResponse);
    

    Note how the response is (GreetResponse rather than stream GreetResponse). For this kind of call a SendAndClose function will be generated. The server can keep receiving as long as the client is sending, but also has the option to send a (single) response (and end the call) using the SendAndClose function. See this example.

    The rpc call your question is about is a bidirectional stream (both the request and response are streams):

    rpc LongGreet (stream GreetRequest) returns (stream GreetResponse);
    

    For this call type no SendAndClose function is generated; as the tutorial says:

    The syntax for reading and writing here is very similar to our client-streaming method, except the server uses the stream’s Send() method rather than SendAndClose() because it’s writing multiple responses.

    When writing your Go code to implement this you can call Send as often as you want (to send data over the stream). When you are done call CloseSend - see this example in the tutorial (note that the two streams operate independently.). No SendAndClose function is generated because the server is sending a stream (so Send and CloseSend are seperate actions).