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
中然後內嵌進來