一个通用的客户端示例,确保正确的关闭stream
代码语言:javascript复制func sendStreamExample() error {
ctx, cancel := context.WithCancel(context.Background())
// 注意退出前一定cancel,避免异常的时候stream泄露
defer cancel()
stream, err := client.RouteChat(ctx)
if err != nil{
return err
}
waitc := make(chan error)
go func() {
for {
// 即使服务端不会回包,也要等待Eof信号
in, err := stream.Recv()
if err == io.EOF {
// 正常,send完数据后,发送closeSend,等待recv到Eof,则代表一次发送正常结束
close(waitc)
return
}
if err != nil {
cancel()
// 异常,收到其它错误则应该进入错误流程中
waitc <- err
return
}
}
}()
// 开始发送数据
for note := range notes {
err = stream.Send(note)
if err != nil {
// send正常情况下不应该收到任何错误,发现错误则应该终止并进入错误处理
cancel()
return err
}
}
// 当所有的消息被发送完毕,则调用closeSend,此时应该在Recv处等待Eof错误,代表服务端已经正常全部接收完所有消息
stream.CloseSend()
err = <-waitc
if err != nil {
return err
}
return nil
}