protoc-生成go指针
这里指的是为结构体中基础类型生成go指针,嵌套结构体默认就是指针
为什么需要生成指针?
因为在一些场景中指针表示的含义是比类型表示的多的
type user struct {
name string
address string
}
假设上述结构体表示一个用户的信息,创建用户后希望更新用户名时该怎么实现?这里隐藏的一个问题就是:address
为空字符串时,到底是表示不更新该字段?还是表示将该字段置为空?
type user struct {
name string
address *string
}
使用指针的意义就是该字段可以额外表示一重含义
-
address
字段可以为空字符串 -
address
字段可以为非空字符串 -
address
字段可以直接为nil
,表示该字段无效
proto3生成指针的方法
proto2的结构体字段除了
repeated
外默认就是指针,不过多说明了
protoc
:libprotoc 3.17.3
protoc-gen-go
:1.5.2
optional关键字
在
proto3
最开始去掉了optional
字段,但是后续又加回来了
syntax = "proto3";
package exp;
option go_package = "./go";
message T {
optional int32 intPtr = 1;
}
protoc --go_out=./ exp.proto
optional
对于protoc
和protoc-gen-go
的版本都是有依赖的,在低版本中还需要带上额外字段
protoc --experimental_allow_proto3_optional --go_out=./ exp.proto
[需要带上--experimental_allow_proto3_optional](protocol buffers - How to define an optional field in protobuf 3 - Stack Overflow)
gogo/protobuf
gogo/protobuf
是在protobuf
基础上开发出来的一些工具,支持一些扩展语法之类的,使用也是比较广泛的
使用上面同样的protoc
文件,发现是无法支持的
protoc --gofast_out=./ exp.proto
exp.proto: is a proto3 file that contains optional fields, but code generator protoc-gen-gofast hasn't been updated to support optional fields in proto3. Please ask the owner of this code generator to support proto3 optional.--gofast_out:
在gogo/protobuf
还未支持optional
的语法,一种可行的解法就是在proto3
中导入proto2
的文件,并且把需要定义为指针的字段放在proto2
中
wktpointer扩展语法
syntax = "proto3";
package exp;
import "google/protobuf/wrappers.proto";
import "github.com/gogo/[email protected]/gogoproto/gogo.proto";
option go_package = "./go";
message T {
google.protobuf.Int32Value intPtr = 1 [(gogoproto.wktpointer) = true];
}
type T struct {
IntPtr *int32 `protobuf:"bytes,1,opt,name=intPtr,proto3,wktptr" json:"intPtr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
不过在网络上很难找到wktptr
的介绍,这个语法也非常让人困惑
nullable
syntax = "proto3";
package exp;
//import "google/protobuf/wrappers.proto";
import "github.com/gogo/[email protected]/gogoproto/gogo.proto";
option go_package = "./go";
message T {
int32 intPtr = 1 [(gogoproto.nullable) = false];
}
ERROR: field T.IntPtr is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values--gofast_out: protoc-gen-gofast: Plugin failed with status code 1.
nullable
扩展字段无法支持原生类型,此扩展字段对此是无效的
embed
最简单的方法就是通过
import
的方式在proto3
中加载proto2
的语法,但是实际上通过内嵌结构体的方式来优化一下
message T {
S s = 1 [(gogoproto.embed)=true];
}
这样可以将需要定义为指针的元素定义到proto2
中然后内嵌进来