Protobuf inject tag ----------------- ###### tags: `Protobuf` # Proto go inject tag [link](https://github.com/favadi/protoc-go-inject-tag) 使用protobuf於各種DAO、DTO時, 往往因為需要對各種tag做不同的解析, protobuf產出的struct又沒這些tag, 以前就很認命的做一些pb->dao/dto, dao是為了加入orm的tag還有protoc自動產生的XXX屬性如果直接用, 則table根本沒這些欄位. dto有些是為了忽略或者加入一些valid tag. 有大神做出套件, 能透過註解的形式把tag給注入到生產出來的protobuf structre內. ## Install ```bash go get github.com/favadi/protoc-go-inject-tag ``` ## Usage 透過`// @inject_tag: custom_tag:"custom_value"`在proto需要的屬性上加入該行 ```go // file: test.proto syntax = "proto3"; package pb; message IP { // @inject_tag: valid:"ip" string Address = 1; } ``` 執行編譯 ```bash // protoc編譯並生成pb.go檔 protoc --go_out=. test.proto // 透過protoc-go-inject-tag, 讀取pb.go檔, 並改寫pb.go檔 protoc-go-inject-tag -input=./test.pb.go ``` 就會產生下面的go struct, 其中Address就會帶入valid:"ip". 但也會發現XXX_*的屬性, 只有json:"-", XXX又大寫, 如果直接給ORM使用, 會被當成table欄位給使用. ```go type IP struct { // @inject_tag: valid:"ip" Address string `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty" valid:"ip"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` } ``` ### 忽略XXX_*的欄位 透過protoc-go-inject-tag編譯時加上--XXX_skip=tag1,tag2就能 ```go syntax = "proto3"; package pb; import "google/protobuf/timestamp.proto"; message IP { // @inject_tag: valid:"ip" string Address = 1; // @inject_tag: sql:",notnull,default:false" bool completed = 3; // @inject_tag: sql:"type:timestamptz,default:now()" google.protobuf.Timestamp created_at = 5; // @inject_tag: sql:”type:timestamptz” google.protobuf.Timestamp updated_at = 6; } ``` 執行編譯 ```bash // protoc編譯並生成pb.go檔 protoc --go_out=. test.proto // 透過protoc-go-inject-tag, 讀取pb.go檔, 並改寫pb.go檔 protoc-go-inject-tag -input=./test.pb.go --XXX_skip=xorm,sql ``` ```go type IP struct { // @inject_tag: valid:"ip" Address string `protobuf:"bytes,1,opt,name=Address,proto3" json:"Address,omitempty" valid:"ip"` // @inject_tag: sql:",notnull,default:false" Completed bool `protobuf:"varint,3,opt,name=completed,proto3" json:"completed,omitempty" sql:",notnull,default:false"` // @inject_tag: sql:"type:timestamptz,default:now()" CreatedAt *timestamp.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty" sql:"type:timestamptz,default:now()"` // @inject_tag: sql:”type:timestamptz” UpdatedAt *timestamp.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-" xorm:"-" sql:"-"` XXX_unrecognized []byte `json:"-" xorm:"-" sql:"-"` XXX_sizecache int32 `json:"-" xorm:"-" sql:"-"` } ``` # Conclusion 這套件真是福音QQ 如果沒這套件, 就是得做轉換器, 在執行過程中轉換, 對效能很講究的場景下, 挺脫褲子放屁, Model數量也會暴增. 現在可以一個model就吃下pb、DAO 、DTO了^^