Protobuf 3 是一种高效的数据序列化格式,但在使用过程中,有时需要将某些字段设为必填字段。那么,如何使 Protobuf 3 字段成为必填字段呢?在本文中,php小编草莓将为您详细介绍如何使用 Protobuf 3 的特性来实现字段必填,并提供相应的代码示例。无论您是初学者还是有一定经验的开发者,本文都能帮助您快速掌握必填字段的使用方法,提升代码的健壮性和可靠性。让我们一起来看看吧!
问题内容
我正在使用 grpc/proto-buffers 在 golang 中编写我的第一个 api 端点。我对 go 还很陌生。 以下是我为测试用例编写的文件
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)
})
}
这是在上面包含的 v1.go
文件中定义 endpointrequest
对象的方式:
// 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
是一个至少包含 1 的字符串。因此,如果省略 a
,端点将返回 400。
但现在我想确保如果省略 c
或 b
端点返回 400。我怎样才能做到这一点?在 protobufs 3 中,他们删除了 required
关键字。那么我如何检查是否传入了非字符串参数并做出相应的反应?
解决方法
简短的版本:你不能。
required
被删除主要是因为它使更改向后不兼容。尝试使用验证选项重新实现它并不是那么激烈(更改更容易),但会遇到如您所见的缺点。
相反,将验证保留在原型定义之外,并将其移至应用程序本身。每当您收到消息时,您都应该检查其内容(当 required
出现时也是如此)。在极少数情况下,由 options 或 required
提供的简单验证就足够了。