場景
需要使用go-playground/validator對入參進行更細致的驗證, (一來相比其他grpc validator plugin, 這個包功能完善一些, 二來項目中使用的gin框架也是依賴於才此包, 保持統一)
當然其他場景可能有一些其他需求, 需要對protobuf文件編譯出來的結構體, 添加上一些自定義的tag
問題
如果使用的是官方的protoc-gen-go, 則截止目前(2021.1.10), 仍未支持這個功能, 相關討論可見:
https://github.com/golang/protobuf/issues/52
解決辦法
1、使用gogo/protobuf, 並且使用其自己的插件
https://github.com/gogo/protobuf
demo: https://github.com/gogo/protobuf/blob/master/test/tags/tags.proto
2、使用工具修改編譯出來的文件(最終采用)
使用的工具是: https://github.com/favadi/protoc-go-inject-tag
最后只需要修改編譯protobuf文件的的shell腳本, 新增類似以下邏輯:
(如果你每次編譯protobuf文件都是手輸命令, 建議寫到shell腳本里)
for file in ${pb_go_files[@]} # pb_go_files即編譯出來的*.pb.go文件名
do
if ! command -v protoc-go-inject-tag > /dev/null 2>&1; then
`cd ~ && go get github.com/favadi/protoc-go-inject-tag` # 因為項目有可能是gomodule模式, 所以進入home目錄再下載
fi
protoc-go-inject-tag -input=./pb/${file}
done
簡單review了一下這個工具的實現, 使用的是go/parser包對代碼進行語義分析后注入的tag, 並不是特別hack的方法, 所以還是挺靠得住的
最終采用該方法的原因主要是:
- 穩妥起見不想替換官方的protoc-gen-go,
- 相對而言對proto文件的修改是以注釋的形式, 侵入性較低, 且語法也比較簡潔, 團隊應該更容易接受一些
