Go Struct 中的 Go Protobuf 声明和可选字段(字符串指针)
Go Protobuf declarations and optional Fields in Go Struct (string pointers)
我 运行 Protoc 和我现有的包含可为空字符串字段的结构有点问题。
我试图序列化以进行传输的结构包含一堆在 json 中可为空的字段(因此我们可以区分 null
、""
和设置值) .
type Message struct {
Path *string `json:"path"`
}
因此,如果用户发送一个空的 json 字符串 {}
,路径将是 nil
而不是 ""
,而 {"path":""}
也是有效的并且与 {"path": null}
.
不同的情况
我提出的 proto3
声明显然看起来像这样(并且是可选的,因为 required
和 optional
从 proto3 中删除:
syntax = "proto3";
message Message {
string Path = 1;
}
在 运行 Protoc 之后,我最终得到一个看起来像这样的结构,所有值都是 string
并且无法将它们声明为 *string
:
type Message struct {
Path string `protobuf:"bytes,1,opt,name=Path,proto3" json:"Path,omitempty"`
}
显然我不能从我现有的结构中分配给这个数组。但即使我用 target.Path = *source.Path
编写乏味的映射代码并进行适当的空指针检查等,我也会失去源结构的三重含义(nil
、""
、"value"
).
关于如何在此处进行的任何建议,或者是否有 Go Protobuf 的扩展来执行此操作?或者如何描述这个原型声明?
Proto3 returns Zero Value 即使未设置字段。目前无法区分某个字段是否已设置。
请参阅 Github 问题 #15。
可能的解决方案:
- 使用proto2 instead of proto3.
- 使用 gogoproto 的 nullable 扩展。
- 使用
google.protobuf.FieldMask
扩展,参见通用设计模式
来自 Google API 设计指南:Partial Responses and Output Fields.
就我而言,我用几个包解决了这个问题:
我的原型文件如下所示:
syntax = "proto3";
import "google/protobuf/wrappers.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message Message {
google.protobuf.StringValue path = 1 [(gogoproto.wktpointer) = true];
}
生成go代码的命令,我用的是这样的:
protoc -I. -I%GOPATH%/src --gogofaster_out=plugins=grpc:. proto/*.proto
生成的 go 文件如下所示:
type Message struct {
Path *string `protobuf:"bytes,1,opt,name=path,json=path,proto3,wktptr" json:"path,omitempty"`
}
proto3 支持可选,带有标志 --experimental_allow_proto3_optional
我 运行 Protoc 和我现有的包含可为空字符串字段的结构有点问题。
我试图序列化以进行传输的结构包含一堆在 json 中可为空的字段(因此我们可以区分 null
、""
和设置值) .
type Message struct {
Path *string `json:"path"`
}
因此,如果用户发送一个空的 json 字符串 {}
,路径将是 nil
而不是 ""
,而 {"path":""}
也是有效的并且与 {"path": null}
.
我提出的 proto3
声明显然看起来像这样(并且是可选的,因为 required
和 optional
从 proto3 中删除:
syntax = "proto3";
message Message {
string Path = 1;
}
在 运行 Protoc 之后,我最终得到一个看起来像这样的结构,所有值都是 string
并且无法将它们声明为 *string
:
type Message struct {
Path string `protobuf:"bytes,1,opt,name=Path,proto3" json:"Path,omitempty"`
}
显然我不能从我现有的结构中分配给这个数组。但即使我用 target.Path = *source.Path
编写乏味的映射代码并进行适当的空指针检查等,我也会失去源结构的三重含义(nil
、""
、"value"
).
关于如何在此处进行的任何建议,或者是否有 Go Protobuf 的扩展来执行此操作?或者如何描述这个原型声明?
Proto3 returns Zero Value 即使未设置字段。目前无法区分某个字段是否已设置。
请参阅 Github 问题 #15。
可能的解决方案:
- 使用proto2 instead of proto3.
- 使用 gogoproto 的 nullable 扩展。
- 使用
google.protobuf.FieldMask
扩展,参见通用设计模式 来自 Google API 设计指南:Partial Responses and Output Fields.
就我而言,我用几个包解决了这个问题:
我的原型文件如下所示:
syntax = "proto3";
import "google/protobuf/wrappers.proto";
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
message Message {
google.protobuf.StringValue path = 1 [(gogoproto.wktpointer) = true];
}
生成go代码的命令,我用的是这样的:
protoc -I. -I%GOPATH%/src --gogofaster_out=plugins=grpc:. proto/*.proto
生成的 go 文件如下所示:
type Message struct {
Path *string `protobuf:"bytes,1,opt,name=path,json=path,proto3,wktptr" json:"path,omitempty"`
}
--experimental_allow_proto3_optional