2 回答
TA贡献1871条经验 获得超8个赞
使用人为的服务器示例进一步调查:
func (s *mygRPC) GetStatus(context.Context, *empty.Empty) (*pb.Status, error) {
log.Println("cli: GetStatus()")
//return &pb.Status{}, nil
return nil, nil // <- can server return a nil status message (with nil error)
}
并测试客户端/服务器的反应:
客户:
ERROR: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil
服务器:
2019/05/14 16:09:50 cli: GetStatus()
ERROR: 2019/05/14 16:09:50 grpc: server failed to encode response: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil
因此,即使想要合法地返回一个 nil 值,gRPC传输也不会允许。
注意:服务器端代码仍在执行 - 正如预期的那样 - 但就客户端而言,调用gRPC失败了。
结论:有效的 ( err==nil) 服务器响应将始终返回有效的 ( 非nil) 消息。
编辑:
检查源代码可以揭示捕获消息的gRPC位置:nil
服务器.go
func (s *Server) sendResponse(t transport.ServerTransport, stream *transport.Stream, msg interface{}, cp Compressor, opts *transport.Options, comp encoding.Compressor) error {
data, err := encode(s.getCodec(stream.ContentSubtype()), msg)
if err != nil {
grpclog.Errorln("grpc: server failed to encode response: ", err)
return err
}
// ...
}
rpc_util.go
func encode(c baseCodec, msg interface{}) ([]byte, error) {
if msg == nil { // NOTE: typed nils will not be caught by this check
return nil, nil
}
b, err := c.Marshal(msg)
if err != nil {
return nil, status.Errorf(codes.Internal, "grpc: error while marshaling: %v", err.Error())
}
// ...
}
这一行的评论是关键:
if msg == nil { // NOTE: typed nils will not be caught by this check }
因此,如果要对我们的 typed-nil 使用 reflect,reflect.ValueOf(msg).IsNil()将返回true. 以下c.Marshal(msg)错误 - 调用无法向客户端发送消息响应。
- 2 回答
- 0 关注
- 126 浏览
添加回答
举报