如何在protobuf中只读自动生成的唯一ID字段?

问题描述

我对 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 仍然可以在请求负载中传递,但实际上会被忽略,因为 id 中的 ToDo 字段仅与读取响应相关。

例如,在下面的 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,"failed to retrieve id for created ToDo-> "+err.Error())
    }

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

在我看来,这在向服务发出请求时有点令人困惑,因为可以假设应该提供 id,但实际上不应该提供。由于 protobuf 中没有 readonly 字段,是否是为 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 成为“只读”而将所有其他字段定义两次似乎很乏味。

解决方法

您也可以撰写消息

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;
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...