go - 如何强制 Protobuf 3 字段?
问题描述
我正在使用 GRPC/proto-buffers 在 GoLang 中编写我的第一个 API 端点。我对 GoLang 比较陌生。以下是我为测试用例编写的文件
package my_package
import (
"context"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/types/known/structpb"
"github.com/MyTeam/myproject/cmd/eventstream/setup"
v1handler "github.com/MyTeam/myproject/internal/handlers/myproject/v1"
v1interface "github.com/MyTeam/myproject/proto/.gen/go/myteam/myproject/v1"
)
func TestEndpoint(t *testing.T) {
conf := &setup.Config{}
// Initialize our API handlers
myhandler := v1handler.New(&v1handler.Config{})
t.Run("Success", func(t *testing.T) {
res, err := myhandler.Endpoint(context.Background(), &v1interface.EndpointRequest{
A: "S",
B: &structpb.Struct{
Fields: map[string]*structpb.Value{
"T": &structpb.Value{
Kind: &structpb.Value_StringValue{
StringValue: "U",
},
},
"V": &structpb.Value{
Kind: &structpb.Value_StringValue{
StringValue: "W",
},
},
},
},
C: ×tamppb.Timestamp{Seconds: 1590179525, Nanos: 0},
})
require.Nil(t, err)
// Assert we got what we want.
require.Equal(t, "Ok", res.Text)
})
}
这是在上面包含的文件EndpointRequest
中定义对象的方式:v1.go
// An v1 interface Endpoint Request object.
message EndpointRequest {
// a is something.
string a = 1 [(validate.rules).string.min_len = 1];
// b can be a complex object.
google.protobuf.Struct b = 2;
// c is a timestamp.
google.protobuf.Timestamp c = 3;
}
上面的测试用例似乎工作正常。
我设置了有效地使参数成为a
强制性的验证规则,因为它要求它a
至少是一个字符串。因此,如果您省略a
,端点将返回 400。
但现在我想确保端点返回 400 如果c
或被b
省略。我怎样才能做到这一点?在 Protobufs 3 中,他们去掉了required
关键字。那么如何检查是否传入了非字符串参数并做出相应的反应呢?
解决方案
中删除了必填字段proto3
。这是 github 问题,您可以在其中阅读详细说明为什么这样做。这是摘录:
我们在 proto3 中删除了必填字段,因为必填字段通常被认为是有害的并且违反了 protobuf 的兼容性语义。使用 protobuf 的整个想法是,它允许您从协议定义中添加/删除字段,同时仍然与较新/较旧的二进制文件完全向前/向后兼容。必填字段打破了这一点。您永远不能安全地将必填字段添加到 .proto 定义中,也不能安全地删除现有的必填字段,因为这两个操作都会破坏线路兼容性
IMO,这是一个有问题的决定,显然我并不孤单,谁在这么想。最终决定应该留给开发商。
推荐阅读
- android - 使用 Firebase UI 时为 RecyclerView 初始化 firebase 参考
- ios - Xcode 10 框架依赖循环与自身
- python - 自定义渲染器破坏站点
- sql-server - 查询 Outlook 服务器以获取日历项目和详细信息
- asp.net - 如果重新验证有效,如何启用按钮
- php - 在 Windows 中的 PHP 中,“换行 (LF)”和“回车 (CR)”是否表示相同的意思?
- c - 限制为数组大小的目的是什么?
- css - 为什么 Columns 类中的子项以单行显示?
- c# - 为什么在这里寻找 VsixUtil.exe 的东西?
- python - python:在Itertools产品对象上调用set第二次清除数据