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

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;
}

在这种情况下,弃用和在原型中创建新字段的首选方式也是如此吗?

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:optional Proto3 中的字段从版本 3.15 开始得到支持

取决于特定消息在您的代码库中的集成程度 - 意思是

  1. 您是否将编组的二进制表示存储在数据库之类的地方
  2. 您的代码库的不同部分使用您正在修改的消息的不同版本 - 例如您的 android/ios 应用的旧版本等

要点是,如果您使用消息结构来解组编码数据(不是使用完全相同的消息结构生成的),就会发生坏事。

文档建议添加一个新元素以完全避免此类情况。如果您不想这样做,请考虑以上几点。

我建议您使用 FloatValue type defined in the google.protobuf 包。例如:


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()
  }