protobuf導(dǎo)出golang植康,調(diào)整默認tag的方法
問題概述
在protobuf導(dǎo)出到golang的時候彤灶,生成的.go文件里的struct的tag是沒辦法靈活設(shè)置的看幼,以下面這個message為例
test.proto
syntax=proto3;
package test;
option go_package = ".;test";
message MyMessage {
int64 Code = 1;
}
執(zhí)行protoc --proto_path=. --go_out=. test.proto導(dǎo)出的test.pb.go里的MyMessage這個結(jié)構(gòu)體的定義會是這樣:
type MyMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Code int64 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
}
可以看到Code字段的protobuf和json的tag都是固定的(目前還沒有找到方法能通過protoc命令的參數(shù)來設(shè)置tag),但是這樣的struct有時候并不是我們所期待的幌陕,比如下面的代碼片段:
msg := &MyMessage{Code: 0}
bdata, _ := json.Marshal(msg)
fmt.Println(string(bdata))
這段代碼最終的輸出會是{}
诵姜,因為Code的json tag設(shè)置了omitempty,這種情況在開發(fā)過程中有時候是很蛋疼的搏熄,因為即便Code是默認值0棚唆,我們也還是希望能打印出來的。因此我們需要一種方法能通過在編寫proto文件的時候心例,在里面注入tag宵凌,然后導(dǎo)出成go的時候這個被注入的字段的tag可以自定義。
解決方法
- protoc-go-inject-tag: https://github.com/favadi/protoc-go-inject-tag
- 安裝:go get https://github.com/favadi/protoc-go-inject-tag
- 這個庫可以在proto文件中注入tag止后,然后在導(dǎo)出的時候相應(yīng)的字段的tag就可以被修改掉了瞎惫。具體做法如下:
test.proto
syntax=proto3;
package test;
option go_package = ".;test";
message MyMessage {
// @inject_tag: json:"Code"
int64 Code = 1;
}
可以看到與之前不同的是我們在Code這個字段上面加了一行注釋// @inject_tag: json:"Code"
。
執(zhí)行
protoc --proto_path=. --go_out=. test.proto
protoprotoc-go-inject-tag -input=./test.pb.go
這時候?qū)С龅膖est.pb.go文件里的MyMessage結(jié)構(gòu)體如下:
type MyMessage struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// @inject_tag: json:"Code"
Code int64 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code"`
}
可以看到Code字段的json tag里的omitempty沒有了译株,這時候如果我們再執(zhí)行
msg := &MyMessage{Code: 0}
bdata, _ := json.Marshal(msg)
fmt.Println(string(bdata))
這個代碼片段瓜喇,輸出就是{"Code": 0}
了。達到我們的目的了歉糜。當然inject_tag不僅僅可以設(shè)置json的tag乘寒,它可以設(shè)置任何的tag。
總結(jié)
protobuf的protoc工具導(dǎo)出golang的時候现恼,導(dǎo)出的結(jié)構(gòu)體的tag是固定死的,在實際的使用中會導(dǎo)致很多不方便或是不靈活黍檩,通過protoc-go-inject-tag這個工具叉袍,可以inject tag,這樣就能靈活的調(diào)整導(dǎo)出的pb.go文件里的結(jié)構(gòu)體的tag刽酱。