英文:
Change an existing field of value type float to an optional float in a protobuf message
问题
我有以下类型的消息:
message Foo {
string bar = 1;
float baz = 2;
}
将其转换为以下形式以在Go中使用是否有问题?
message Foo {
string bar = 1;
optional float baz = 2;
}
在这种情况下,是否首选废弃并在proto中创建一个新字段?
英文:
I have a message of the following type
message Foo {
string bar = 1;
float baz = 2;
}
Is there any problem in converting it to the following for use in Go ?
message Foo {
string bar = 1;
optional float baz = 2;
}
Is the preferred way to deprecate and create a new field in the proto in this case as well ?
答案1
得分: 0
optional
将使字段成为指针类型。因此,在生成的Go代码中,optional float
将变为*float32
,当然不是float32
。
要弃用一个字段,请使用[deprecated = true]
字段选项:
message Foo {
string bar = 1;
float baz = 2 [deprecated = true];
}
如果在后续版本的protobuf模式中,你实际上从消息中完全删除了该字段,你可能想要添加reserved 2
,其中2
是你删除的字段的编号。
message Foo {
string bar = 1;
reserved 2;
}
这有助于防止其他人或未来的你在位置2添加新字段。这在你有过时的客户端仍然期望在位置2上有一个float
时是相关的。
PS:Proto3中的optional
字段从3.15版本开始支持。
英文:
The optional
will make the field a pointer type. So in Go generated code, optional float
will become *float32
, which of course is not float32
.
To deprecate a field, use [deprecated = true]
field option:
message Foo {
string bar = 1;
float baz = 2 [deprecated = true];
}
If in subsequent releases of your protobuf schema you actually remove the field altogether from the message, you might want to add reserved 2
, where 2
is the number of the field you removed.
message Foo {
string bar = 1;
reserved 2;
}
This helps preventing other people or future you from adding a new field in position 2. This is relevant in case you have outdated clients which still expect a float
in position 2.
PS: optional
fieds in Proto3 are supported from version 3.15
答案2
得分: 0
这取决于该特定消息在你的代码库中的集成程度,也就是说:
- 你是否将编组的二进制表示存储在某个地方,比如数据库?
- 你的代码库的不同部分是否在使用你正在修改的消息的不同版本,比如旧版本的 Android/iOS 应用等?
关键在于,如果你使用消息结构来解组编码数据,而该数据的生成不是使用完全相同的消息结构,那么会发生糟糕的事情。
文档建议添加一个新元素来完全避免这种情况。如果这不是你想要做的事情,那么请考虑上述要点。
英文:
depends on how deeply integrated that particular message is in your code base - meaning
- are you storing the marshaled binary representation somewhere like your database
- are different parts of your code base using different versions of the message you are modifying - e.g. older versions of your android/ios apps and such
point being if you use a message structure to unmarshal encoded data, that was not generated with the very same message structure, into - bad things will happen.
The docs recommend adding a new element to circumvent such scenarios entirely. If that is not something you want to do, take the above points into consideration.
答案3
得分: 0
我建议您使用在google.protobuf
包中定义的FloatValue
类型。例如:
syntax = "proto3";
import "google/protobuf/wrappers.proto";
message Foo {
string bar = 1;
google.protobuf.FloatValue baz = 2;
}
将生成一个包含以下内容的pb文件:
type Foo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Bar string `protobuf:"bytes,1,opt,name=bar,proto3" json:"bar,omitempty"`
Baz *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=baz,proto3" json:"baz,omitempty"`
}
您可以按照以下方式使用:
f := Foo{
Bar: "Bar",
Baz: &wrapperspb.FloatValue{Value: float32(3)},
}
var floatValue float32
if f.Baz != nil {
floatValue = f.Baz.GetValue()
}
英文:
I suggest you to use the FloatValue type defined in the google.protobuf package. As example:
syntax = "proto3";
import "google/protobuf/wrappers.proto";
message Foo {
string bar = 1;
google.protobuf.FloatValue baz = 2;
}
Will generate a pb files with the content:
type Foo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Bar string `protobuf:"bytes,1,opt,name=bar,proto3" json:"bar,omitempty"`
Baz *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=baz,proto3" json:"baz,omitempty"`
}
You can use as follow:
f := Foo{
Bar: "Bar",
Baz: &wrapperspb.FloatValue{Value: float32(3)},
}
var floatValue float32
if f.Baz != nil {
floatValue = f.Baz.GetValue()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论