2 回答

TA貢獻(xiàn)1871條經(jīng)驗(yàn) 獲得超8個(gè)贊
使用人為的服務(wù)器示例進(jìn)一步調(diào)查:
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)
}
并測試客戶端/服務(wù)器的反應(yīng):
客戶:
ERROR: rpc error: code = Internal desc = grpc: error while marshaling: proto: Marshal called with nil
服務(wù)器:
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
因此,即使想要合法地返回一個(gè) nil 值,gRPC傳輸也不會(huì)允許。
注意:服務(wù)器端代碼仍在執(zhí)行 - 正如預(yù)期的那樣 - 但就客戶端而言,調(diào)用gRPC失敗了。
結(jié)論:有效的 ( err==nil) 服務(wù)器響應(yīng)將始終返回有效的 ( 非nil) 消息。
編輯:
檢查源代碼可以揭示捕獲消息的gRPC位置:nil
服務(wù)器.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())
? ? }
? ? // ...
}
這一行的評(píng)論是關(guān)鍵:
if msg == nil { // NOTE: typed nils will not be caught by this check }
因此,如果要對(duì)我們的 typed-nil 使用 reflect,reflect.ValueOf(msg).IsNil()將返回true. 以下c.Marshal(msg)錯(cuò)誤 - 調(diào)用無法向客戶端發(fā)送消息響應(yīng)。
- 2 回答
- 0 關(guān)注
- 161 瀏覽
添加回答
舉報(bào)