Scott

proto文件设置ResponseMessage 为了返回数据的一致性,要求有3个字段:code, message, data. 其中code为数值型,message为string类型,data为任意类型 2 months ago

微服务
1857个字符
共有12人围观

定义通用的 ResponseMessage

以下是一个符合你要求的 Protocol Buffers 响应消息定义,包含 codemessagedata 三个字段,其中 data 为任意类型:

方案1:使用 google.protobuf.Any(推荐)

syntax = "proto3";

import "google/protobuf/any.proto";

message ResponseMessage {
  int32 code = 1;                  // 状态码
  string message = 2;              // 状态信息
  google.protobuf.Any data = 3;    // 响应数据,可以是任意类型
}

方案2:使用 oneof(适用于已知有限类型)

syntax = "proto3";

message ResponseMessage {
  int32 code = 1;
  string message = 2;
  oneof data {
    string string_data = 3;
    int32 int_data = 4;
    bool bool_data = 5;
    bytes binary_data = 6;
    // 可以添加更多已知类型
  }
}

方案3:使用 google.protobuf.Value(类似JSON的灵活性)

syntax = "proto3";

import "google/protobuf/struct.proto";

message ResponseMessage {
  int32 code = 1;
  string message = 2;
  google.protobuf.Value data = 3;  // 可以是null, number, string, bool, list或object
}

推荐实现

推荐使用方案1(Any 类型),因为它:

  1. 可以包装任何 protobuf 消息类型
  2. 是官方标准解决方案
  3. 各语言都有良好的支持库

使用示例(Go语言)

import (
    "google.golang.org/protobuf/types/known/anypb"
)

// 创建响应
func CreateSuccessResponse(data proto.Message) (*ResponseMessage, error) {
    anyData, err := anypb.New(data)
    if err != nil {
        return nil, err
    }
    
    return &ResponseMessage{
        Code:    200,
        Message: "Success",
        Data:    anyData,
    }, nil
}

// 使用示例
user := &User{Name: "John", Age: 30}
resp, err := CreateSuccessResponse(user)

客户端解析示例

// 解析响应
func ParseResponse(resp *ResponseMessage, target proto.Message) error {
    if resp.GetData() != nil {
        return resp.GetData().UnmarshalTo(target)
    }
    return errors.New("no data in response")
}

// 使用示例
var user User
if err := ParseResponse(response, &user); err != nil {
    // 处理错误
}

这种设计模式类似于 REST API 中常见的响应结构,提供了良好的前后端交互一致性。