【发布时间】: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