Implementing Client Streaming RPCs

1. Receiving Client Stream

Example: Server reads client stream

func (s *server) UploadFile(stream filev1.FileService_UploadFileServer) error {
    var total int64
    for {
        chunk, err := stream.Recv()
        if err == io.EOF {
            return stream.SendAndClose(&filev1.UploadResult{Bytes: total})
        }
        if err != nil { return err }
        total += int64(len(chunk.Data))
    }
}
MethodDetail
stream.Recv()Next request or io.EOF
stream.SendAndClose(res)Send final response and close

2. Processing Incoming Messages

PatternDetail
Streaming aggregateSum/count/hash incrementally
Buffered writeWrite each chunk to disk/blob store
Validate per messageFail fast — return error mid-stream

3. Sending Final Response

RuleDetail
Call onceExactly one SendAndClose
After EOF onlyMust consume all client messages first

4. Aggregating Stream Data

Example: Hash + size summary

h := sha256.New()
for {
    c, err := stream.Recv()
    if err == io.EOF {
        return stream.SendAndClose(&filev1.UploadResult{
            Sha256: hex.EncodeToString(h.Sum(nil)),
        })
    }
    if err != nil { return err }
    h.Write(c.Data)
}

5. Creating Client Stream

Example: Open client stream

stream, err := client.UploadFile(ctx)
if err != nil { return err }
NoteDetail
Method takes no requestRequest comes via Send calls
Stream is bound to ctxCanceling ctx aborts the stream

6. Sending Multiple Requests

MethodDetail
stream.Send(msg)Push request
Not concurrency-safeSerialize sends

7. Closing Client Stream

MethodAction
stream.CloseAndRecv()Close send-side and read final response
ReturnsFinal response or error

8. Handling Send Errors

ErrorDetail
io.EOF from SendServer already closed; call CloseAndRecv to get status
Other errorsConnection level — abort

9. Receiving Final Response

Example: Close + receive

for _, chunk := range chunks {
    if err := stream.Send(chunk); err != nil { break }
}
res, err := stream.CloseAndRecv()
if err != nil { return err }
fmt.Println("uploaded", res.Bytes)

10. Using Stream Context

UseAPI
DeadlineSet on ctx passed to method
Server-side ctxstream.Context()
Metadata inmetadata.FromIncomingContext(stream.Context())