Implementing Server Streaming RPCs

1. Creating Streaming Handler

Example: Server stream handler

func (s *server) ListEvents(r *eventv1.ListEventsRequest, stream eventv1.EventService_ListEventsServer) error {
    for _, e := range s.store.Query(r.Filter) {
        if err := stream.Send(e); err != nil { return err }
        if err := stream.Context().Err(); err != nil { return err }
    }
    return nil
}
SignatureDetail
No ctx paramUse stream.Context()
Return nilSignals successful end-of-stream

2. Sending Multiple Responses

MethodBehavior
stream.Send(msg)Push one message; respects flow control
BackpressureBlocks if HTTP/2 window full
ConcurrencySend is not safe for concurrent calls

3. Detecting Client Disconnect

Example: Check ctx in loop

select {
case <-stream.Context().Done():
    return stream.Context().Err()
default:
}
SignalDetail
Send returns errorEOF / connection closed
ctx.Done()Client canceled / deadline hit

4. Handling Stream Errors

SourceAction
Send errorStop producing, return error
Upstream errorWrap with status.Error
Partial successUse trailer metadata or final summary message

5. Creating Client Receiver

Example: Client receives stream

stream, err := client.ListEvents(ctx, &eventv1.ListEventsRequest{Filter: "all"})
if err != nil { return err }
for {
    e, err := stream.Recv()
    if err == io.EOF { break }
    if err != nil { return err }
    process(e)
}

6. Receiving Stream Messages

MethodReturns
stream.Recv()Next message or io.EOF on end
After EOFStream is closed; do not call again

7. Detecting End of Stream

SignalMeaning
err == io.EOFSuccessful clean end
err != nil && err != io.EOFRPC failed — check status

8. Handling Receive Errors

Example: Status-aware receive

e, err := stream.Recv()
if err != nil && err != io.EOF {
    if st, ok := status.FromError(err); ok {
        log.Printf("stream failed: %s %s", st.Code(), st.Message())
    }
}

9. Processing Stream Data

PatternDetail
Process inlineSimple loop body
Channel + workerDecouple receive from processing
BatchAccumulate N then flush for throughput

10. Closing Server Stream

MethodAction
Return nilClean end; client sees io.EOF
Return errorSends trailer with status; client sees error
Set trailerstream.SetTrailer(md) before return