将Protobuf消息中现有的值类型为float的字段更改为可选的float类型。

huangapple go评论114阅读模式
英文:

Change an existing field of value type float to an optional float in a protobuf message

问题

我有以下类型的消息:

  1. message Foo {
  2. string bar = 1;
  3. float baz = 2;
  4. }

将其转换为以下形式以在Go中使用是否有问题?

  1. message Foo {
  2. string bar = 1;
  3. optional float baz = 2;
  4. }

在这种情况下,是否首选废弃并在proto中创建一个新字段?

英文:

I have a message of the following type

  1. message Foo {
  2. string bar = 1;
  3. float baz = 2;
  4. }

Is there any problem in converting it to the following for use in Go ?

  1. message Foo {
  2. string bar = 1;
  3. optional float baz = 2;
  4. }

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]字段选项:

  1. message Foo {
  2. string bar = 1;
  3. float baz = 2 [deprecated = true];
  4. }

如果在后续版本的protobuf模式中,你实际上从消息中完全删除了该字段,你可能想要添加reserved 2,其中2是你删除的字段的编号。

  1. message Foo {
  2. string bar = 1;
  3. reserved 2;
  4. }

这有助于防止其他人或未来的你在位置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:

  1. message Foo {
  2. string bar = 1;
  3. float baz = 2 [deprecated = true];
  4. }

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.

  1. message Foo {
  2. string bar = 1;
  3. reserved 2;
  4. }

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

这取决于该特定消息在你的代码库中的集成程度,也就是说:

  1. 你是否将编组的二进制表示存储在某个地方,比如数据库?
  2. 你的代码库的不同部分是否在使用你正在修改的消息的不同版本,比如旧版本的 Android/iOS 应用等?

关键在于,如果你使用消息结构来解组编码数据,而该数据的生成不是使用完全相同的消息结构,那么会发生糟糕的事情。

文档建议添加一个新元素来完全避免这种情况。如果这不是你想要做的事情,那么请考虑上述要点。

英文:

depends on how deeply integrated that particular message is in your code base - meaning

  1. are you storing the marshaled binary representation somewhere like your database
  2. 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类型。例如:

  1. syntax = "proto3";
  2. import "google/protobuf/wrappers.proto";
  3. message Foo {
  4. string bar = 1;
  5. google.protobuf.FloatValue baz = 2;
  6. }

将生成一个包含以下内容的pb文件:

  1. type Foo struct {
  2. state protoimpl.MessageState
  3. sizeCache protoimpl.SizeCache
  4. unknownFields protoimpl.UnknownFields
  5. Bar string `protobuf:"bytes,1,opt,name=bar,proto3" json:"bar,omitempty"`
  6. Baz *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=baz,proto3" json:"baz,omitempty"`
  7. }

您可以按照以下方式使用:

  1. f := Foo{
  2. Bar: "Bar",
  3. Baz: &wrapperspb.FloatValue{Value: float32(3)},
  4. }
  5. var floatValue float32
  6. if f.Baz != nil {
  7. floatValue = f.Baz.GetValue()
  8. }
英文:

I suggest you to use the FloatValue type defined in the google.protobuf package. As example:

  1. syntax = "proto3";
  2. import "google/protobuf/wrappers.proto";
  3. message Foo {
  4. string bar = 1;
  5. google.protobuf.FloatValue baz = 2;
  6. }

Will generate a pb files with the content:

  1. type Foo struct {
  2. state protoimpl.MessageState
  3. sizeCache protoimpl.SizeCache
  4. unknownFields protoimpl.UnknownFields
  5. Bar string `protobuf:"bytes,1,opt,name=bar,proto3" json:"bar,omitempty"`
  6. Baz *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=baz,proto3" json:"baz,omitempty"`
  7. }

You can use as follow:

  1. f := Foo{
  2. Bar: "Bar",
  3. Baz: &wrapperspb.FloatValue{Value: float32(3)},
  4. }
  5. var floatValue float32
  6. if f.Baz != nil {
  7. floatValue = f.Baz.GetValue()
  8. }

huangapple
  • 本文由 发表于 2021年10月2日 13:28:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/69414245.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定