1. 程式人生 > 其它 >【轉】protoc-go-inject-tag 作用

【轉】protoc-go-inject-tag 作用

原文:https://www.jianshu.com/p/744d8c080d59

----------------------------

protobuf匯出golang,調整預設tag的方法

問題概述

在protobuf匯出到golang的時候,生成的.go檔案裡的struct的tag是沒辦法靈活設定的,以下面這個message為例




test.proto

syntax=proto3;
package test;

option go_package = ".;test";

message MyMessage {
    int64 Code = 1;
}

執行protoc --proto_path=. --go_out=. test.proto匯出的test.pb.go裡的MyMessage這個結構體的定義會是這樣:

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命令的引數來設定tag),但是這樣的struct有時候並不是我們所期待的,比如下面的程式碼片段:

msg := &MyMessage{Code: 0}
bdata, _ := json.Marshal(msg)
fmt.Println(string(bdata))

這段程式碼最終的輸出會是{},因為Code的json tag設定了omitempty,這種情況在開發過程中有時候是很蛋疼的,因為即便Code是預設值0,我們也還是希望能打印出來的。因此我們需要一種方法能通過在編寫proto檔案的時候,在裡面注入tag,然後匯出成go的時候這個被注入的欄位的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"
執行

protoc --proto_path=. --go_out=. test.proto
protoprotoc-go-inject-tag -input=./test.pb.go

這時候匯出的test.pb.go檔案裡的MyMessage結構體如下:

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沒有了,這時候如果我們再執行

msg := &MyMessage{Code: 0}
bdata, _ := json.Marshal(msg)
fmt.Println(string(bdata))

這個程式碼片段,輸出就是{"Code": 0}了。達到我們的目的了。當然inject_tag不僅僅可以設定json的tag,它可以設定任何的tag。

總結

protobuf的protoc工具匯出golang的時候,匯出的結構體的tag是固定死的,在實際的使用中會導致很多不方便或是不靈活,通過protoc-go-inject-tag這個工具,可以inject tag,這樣就能靈活的調整匯出的pb.go檔案裡的結構體的tag。



作者:大菜狗RookieDog
連結:https://www.jianshu.com/p/744d8c080d59
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。