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了^^