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 關注
- 153 瀏覽
添加回答
舉報