【问题标题】:How to make auto-generated unique id fields readonly in protobuf?如何在 protobuf 中使自动生成的唯一 id 字段只读?
【发布时间】:2021-01-28 10:42:42
【问题描述】:

我对 protobuf 很陌生,所以请与我交流。

我注意到在 protobuf 消息类型中通常有一个唯一标识符,如下所示:

message ToDo {
    int64 id = 1; // unique id
    string title = 2;
    string description = 3;
    google.protobuf.Timestamp reminder = 4;
}

然后可以在服务中将消息类型用于创建请求,例如

service ToDoService {
  rpc Create(Todo) returns (CreateResponse) {}
}

我的预期行为是使用插入数据库时​​生成的id 处理请求。但是,这意味着 id 仍然可以在请求负载中传递,但基本上会被忽略,因为 ToDo 中的 id 字段仅与读取响应相关。

例如,todo.Id 在下面的Create 方法中根本没有被引用。

func (s *toDoServiceServer) Create(ctx context.Context, todo *v1.ToDo) (*v1.CreateResponse, error) {
    
    // ... not relevant

    // insert ToDo entity data
    res, err := c.ExecContext(ctx, "INSERT INTO ToDo(`Title`, `Description`, `Reminder`) VALUES(?, ?, ?)",
        todo.ToDo.Title, todo.ToDo.Description, reminder)
    if err != nil {
        return nil, status.Error(codes.Unknown, "failed to insert into ToDo-> "+err.Error())
    }

    // get ID of creates ToDo
    id, err := res.LastInsertId()
    if err != nil {
        return nil, status.Error(codes.Unknown, "failed to retrieve id for created ToDo-> "+err.Error())
    }

    return &v1.CreateResponse{
        Id:  id,
    }, nil
}

在我看来,向服务发出请求时这有点令人困惑,因为可以假设应该提供 id,但实际上不应该提供。由于 protobuf 中没有只读字段,对于 ToDo 有两种不同消息类型的唯一选择是,其中id 只存在于一个中?例如

message ToDoRequest {
    // no id
    string title = 1;
    string description = 2;
    google.protobuf.Timestamp reminder = 3;
}

message ToDo {
    int64 id = 1; // unique id
    string title = 2;
    string description = 3;
    google.protobuf.Timestamp reminder = 4;
}

这样ToDoRequest 仅用于创建/更新请求,ToDo 仅用于读取响应。我唯一的问题是,为了使 id 为“只读”,将所有其他字段定义两次似乎很乏味。

【问题讨论】:

    标签: go protocol-buffers rpc


    【解决方案1】:

    你也可以写消息

    syntax = "proto3";
    
    package todo;
    
    import "google/protobuf/timestamp.proto";
    
    message ToDo {
        string title = 1;
        string description = 2;
        google.protobuf.Timestamp reminder = 3;
    }
    
    message ToDoEntity {
        int64 id = 1;
        ToDo todo = 2;
    }
    
    message ToDoRequest {
        ToDo todo = 1;
    }
    

    【讨论】:

    • 感谢您的回复。我知道这种方法,但我不太喜欢它,因为 id 在层次结构中的级别高于其他字段。可能是我太挑剔了……
    猜你喜欢
    • 2014-01-07
    • 2017-03-27
    • 1970-01-01
    • 2016-09-27
    • 2013-06-11
    • 2013-05-31
    • 1970-01-01
    • 1970-01-01
    • 2018-12-26
    相关资源
    最近更新 更多